Подтвердить что ты не робот

С# как правильно распоряжаться SmtpClient?

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

Предупреждение 4 CA2000: Microsoft.Reliability: в методе 'Mailer.SendMessage()' объект 'клиент' не расположен по всем путям исключений. Вызовите System.IDisposable.Dispose на объекте "клиент", прежде чем все ссылки на него выйдут из области видимости.

Мой код:

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

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

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

Обновление:, чтобы ответить на вопрос Jons, вот функциональность утилиты вложения:

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; 
    }
    }
4b9b3361

Ответ 1

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(); 
    }
}

Ответ 2

Класс 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.

Ответ 3

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

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

Ответ 4

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

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

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

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

Ответ 6

public void SendMessage()
{
    try
    {
        using (SmtpClient client = new SmtpClient())
        {
            client.Send(Message);
        client.dispose()

        }
    }
    finally
    {
        DisposeAttachments(); 
    }
}