VS 2010代码分析报告如下:
警告4 CA2000:Microsoft.Reliability:在方法'Mailer.SendMessage()'中,对象'client'未沿所有异常路径放置。对所有对它的引用超出范围之前,在对象'client'上调用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;
}
}
答案 0 :(得分:47)
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();
}
}
答案 1 :(得分:12)
.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下正确编译和运行。
答案 2 :(得分:7)
using (SmtpClient client = new SmtpClient())
{
client.Send(Message);
DisposeAttachments();
}
有趣 - 与.NET 3.5相反,SmtpClient在.NET 4.0中实现IDisposable,每天都在学习新东西。
答案 3 :(得分:5)
我会做那样的事情:
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对象。
答案 4 :(得分:2)
这是通过代码警察测试的更整洁的解决方案(如果发送失败,将始终调用dispose):
public void SendMessage()
{
using (SmtpClient client = new SmtpClient())
{
client.Send(Message);
DisposeAttachments();
}
}
答案 5 :(得分:0)
我最初的问题是关于间歇性发送失败。
例如。第一个 Send()
成功,第二个 Send()
失败,第三个 Send()
成功。
起初我以为我没有正确处理。
所以我求助于using()
。
无论如何,后来我添加了 UseDefaultCredentials = false,
,Send()
终于稳定了。我仍然保留了 using()
函数。
答案 6 :(得分:-4)
public void SendMessage()
{
try
{
using (SmtpClient client = new SmtpClient())
{
client.Send(Message);
client.dispose()
}
}
finally
{
DisposeAttachments();
}
}