使用另一个 IDisposable 实现 IDisposable 的对象

Objects implementing IDisposable using another IDisposable

我尝试用 C# 开发一个应用程序并且对 MailMessage 对象有一些担忧:

它实现了IDisposable接口,所以我在using语句中使用它。所以它在之后隐式调用 Dispose 方法。现在,使用该对象我需要添加附件,我已将其转换为 byte[] 对象并将它们添加为流。下面是部分代码以获得更好的视图:

using(MailMessage message = new MailMessage("john.smith@gmail.com"){
    MemoryStream stream;
    //here I pass byte array to the stream and create an attachemnt
    message.Attachments.Add(new Attachment(stream, "name.xyz"));

    using(SmtpClient client = new SmtpClient("server.com", port))
    {
        // send message
    }
}

现在,我有一个非托管资源:Stream 对象。我无法在设置附件后立即关闭它(因此无法调用 Dispose 方法),因为发送消息时会出错,因为它在发送时使用流。

所以,我需要稍后删除它,这是我在发送后所做的。那是第二个 using:

中的代码
try
{
    client.Send(messgae);
}
finally
{
    if(stream != null)
        stream.Dispose();
}

现在的问题是:MailMesssageDispose 方法释放了该对象使用的所有资源。我的 Stream 对象是资源之一,不是吗?所以,当 using(MailMessage... 终止时,它也应该管理我的 Stream 对象,不是吗?所以我不需要手动处理我的 Stream 对象。

编辑:

建议的方法:

using(MailMessage message = new MailMessage("john.smith@gmail.com"){
    using(MemoryStream stream = ...)
    {
        //here I pass byte array to the stream and create an attachemnt
        message.Attachments.Add(new Attachment(stream, "name.xyz"));

        using(SmtpClient client = new SmtpClient("server.com", port))
        {
            // send message
        }
    }
}

但问题仍然存在:MailMessage 使用此 Stream - 那么,我们还需要自己管理 Stream 吗?

为什么消息发送后不处理流?

using(MailMessage message = new MailMessage("john.smith@gmail.com"))
{
    using(var stream = new MemoryStream())
    {
        //here I pass byte array to the stream and create an attachemnt
        message.Attachments.Add(new Attachment(stream, "name.xyz"));

        using(SmtpClient client = new SmtpClient("server.com", port))
        {
        // send message
        }
    }
}

试试这个:

using(MailMessage message = new MailMessage("john.smith@gmail.com")
using(MemoryStream stream = new MemoryStream())
using(SmtpClient client = new SmtpClient("server.com", port))
{
    message.Attachments.Add(new Attachment(stream, "name.xyz"))
    client.Send(messgae);
}

如果您将 MemoryStream 放在 using 块中,它将执行与您的 try/finally 块相同的操作。

根据参考文档,您在使用 using 时不需要。

Mail Message disposes Attachment Collection,然后处理所有附件。


关于我们应该采用还是依赖这种方法,我完全同意 Zohar 的观点

Disposing of an IDisposable should be expressed in your code, either by calling Dispose explicitly or with the using statement.