Michał Turczyn
Michał Turczyn

Reputation: 37470

Objects implementing IDisposable using another IDisposable

I try to develop an application in C# and have some concerns with MailMessage object:

it implements IDisposable interface, so I use it within using statement. So it implicitly calls Dispose method after. Now, using that object I need to add attachments, which I have converted to byte[] object and I add them as stream. Here's part of code to have better view:

using(MailMessage message = new MailMessage("[email protected]"){
    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
    }
}

Now, I have one resource unmanaged: Stream object. I can't close it (so can't call Dispose method) right after setting attachments, because I'd get an error when sending message, because it uses the stream while sending.

So, I need to get rid of it later, which I do after sending. That's the code in second using:

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

Now the question: Dispose method of MailMesssage frees all resources used by that object. My Stream object is one of the resources, isn't it? So, when using(MailMessage... terminates it should manage also my Stream object, shouldn't it? So I wouldn't need to dispose of my Stream object manually.

EDIT:

Suggested approach:

using(MailMessage message = new MailMessage("[email protected]"){
    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
        }
    }
}

But the questions stays: MailMessage uses this Stream - so, do we still need to manage Stream on our own?

Upvotes: 0

Views: 210

Answers (3)

ZerosAndOnes
ZerosAndOnes

Reputation: 1093

From the reference documentation you don't need to when you are using using.

Mail Message disposes Attachment Collection, which then disposes all its attachements.


Regarding, should we take or rely on this approach then I totally agree with Zohar on

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

Upvotes: 2

SᴇM
SᴇM

Reputation: 7213

Try this:

using(MailMessage message = new MailMessage("[email protected]")
using(MemoryStream stream = new MemoryStream())
using(SmtpClient client = new SmtpClient("server.com", port))
{
    message.Attachments.Add(new Attachment(stream, "name.xyz"))
    client.Send(messgae);
}

If you put MemoryStream in using block, it will do the same thing as your try/finally block.

Upvotes: 2

Zohar Peled
Zohar Peled

Reputation: 82524

Why not dispose the stream after the message is sent?

using(MailMessage message = new MailMessage("[email protected]"))
{
    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
        }
    }
}

Upvotes: 3

Related Questions