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