C#, как правильно избавиться от SmtpClient?

Анализ кода VS 2010 года сообщает о следующем:

Предупреждение 4 CA2000: Microsoft. Надежность: В методе 'Почтовая программа. SendMessage ()', возражают 'клиент', не расположен вдоль всех путей исключения. Назовите Систему. IDisposable. Расположите на объектном 'клиенте', прежде чем все ссылки на него будут вне объема.

Мой код:

public void SendMessage()
    {
        SmtpClient client = new SmtpClient();

        client.Send(Message);
        client.Dispose(); 
        DisposeAttachments(); 
    }

Как я должен правильно избавиться от клиента?

Обновление: для ответа на вопрос Жонса вот, расположить функциональность вложений:

private void DisposeAttachments()
{
    foreach (Attachment attachment in Message.Attachments)
    {
        attachment.Dispose();
    }
    Message.Attachments.Dispose();
    Message = null; 
}

Последнее обновление полный список классов (его короткое)

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net.Mail;

public class Mailer
    {
    public MailMessage Message
    {
        get;
        set;
    }

    public Mailer(MailMessage message)
    {
        this.Message = message; 
    }

    public void SendMessage()
    {
        using (SmtpClient client = new SmtpClient())
        {
            client.Send(Message);
        }
        DisposeAttachments(); 
    }

    private void DisposeAttachments()
    {
        foreach (Attachment attachment in Message.Attachments)
        {
            attachment.Dispose();
        }
        Message.Attachments.Dispose();
        Message = null; 
    }
    }
31
задан kervin 6 May 2010 в 12:47
поделиться

5 ответов

public void SendMessage()
{
    using (SmtpClient client = new SmtpClient())
    {
        client.Send(Message);
    }
    DisposeAttachments(); 
}

Таким образом, клиент будет удален, даже если во время вызова метода Send возникнет исключение. Вам очень редко нужно вызывать Dispose явно - он почти всегда должен быть в операторе using .

Однако неясно, как здесь задействованы вложения. Реализует ли ваш класс сам IDisposable ? Если это так, то, вероятно, именно здесь можно избавиться от вложений, которые предположительно являются переменными-членами. Если вам нужно быть абсолютно уверенным, что они утилизируются прямо здесь, вам, вероятно, понадобится:

public void SendMessage()
{
    try
    {
        using (SmtpClient client = new SmtpClient())
        {
            client.Send(Message);
        }
    }
    finally
    {
        DisposeAttachments(); 
    }
}
47
ответ дан 27 November 2019 в 21:57
поделиться
using (SmtpClient client = new SmtpClient())
{
    client.Send(Message);
    DisposeAttachments(); 
}

Интересно - в отличие от .NET 3.5, SmtpClient реализует IDisposable в .NET 4.0, изучая что-то новое каждый день.

7
ответ дан 27 November 2019 в 21:57
поделиться

Класс SmtpClient в .NET 4.0 теперь реализует IDisposable , тогда как класс SmtpClient в .NET 2.0 не имеет этого интерфейса (как отметил Дарин). Это критическое изменение в структуре, и вы должны предпринять соответствующие действия при переходе на .NET 4.0. Однако можно уменьшить это в своем коде перед переходом на .NET 4.0. Вот пример такого:

var client = new SmtpClient();

// Do not remove this using. In .NET 4.0 SmtpClient implements IDisposable.
using (client as IDisposable)
{
    client.Send(message);
} 

Этот код будет правильно компилироваться и работать как под .NET 2.0 (+3.0 и 3.5), так и под .NET 4.0.

12
ответ дан 27 November 2019 в 21:57
поделиться

Это более аккуратное решение, которое пройдет тест на полицию кода (и dispose всегда будет вызываться, если Send не удастся):

public void SendMessage()
{
    using (SmtpClient client = new SmtpClient())
    {   
        client.Send(Message);
        DisposeAttachments(); 
    }
}
2
ответ дан 27 November 2019 в 21:57
поделиться

Я бы сделал что-то вроде этого:

class Attachments : List<Attachment>, IDisposable
{
  public void Dispose()
  {
    foreach (Attachment a in this)
    {
      a.Dispose();
    }
  }
}

class Mailer : IDisposable
{
  SmtpClient client = new SmtpClient();
  Attachments attachments = new Attachments();

  public SendMessage()
  {
    [... do mail stuff ...]
  }

  public void Dispose()
  {
    this.client.Dispose();
    this.attachments.Dispose();
  }
}


[... somewhere else ...]
using (Mailer mailer = new Mailer())
{
  mailer.SendMail();
}

Это позволит повторно использовать объект SmtpClient, если вы хотите отправить несколько писем.

5
ответ дан 27 November 2019 в 21:57
поделиться
Другие вопросы по тегам:

Похожие вопросы: