C#如何正确处理SmtpClient?

VS 2010代码分析报告如下:

警告4 CA2000:Microsoft.Reliability:在方法’Mailer.SendMessage()’中,对象’client’未沿所有exception路径放置。 在对所有引用超出范围之前,在对象’client’上调用System.IDisposable.Dispose。

我的代码是:

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

我该如何正确处理客户?

更新:回答Jons问题,这里是dispose附件function:

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

最后更新全class上市(简称)

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

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

这样,即使在Send方法调用期间抛出exception,客户端也将被处置。 您应该很少需要显式调用Dispose – 它应该几乎总是在using语句中。

但是,目前尚不清楚这些附件是如何涉及的。 你的类本身是否实现了IDisposable ? 如果是这样,那可能是处理附件的地方,这些附件可能是成员变量。 如果你需要确保他们在这里处置,你可能需要:

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

.NET 4.0中的SmtpClient类现在实现了IDisposable ,而.NET 2.0中的SmtpClient类缺少此接口(如Darin所说)。 这是框架中的重大更改,您应该在迁移到.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下正确编译和运行。

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

有趣 – 与.NET 3.5相反, SmtpClient在.NET 4.0中实现IDisposable ,每天都在学习新东西。

我会做那样的事情:

 class Attachments : List, 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对象。

这是通过代码警察测试的更整洁的解决方案(如果发送失败,将始终调用dispose):

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