2

I recently came across a situation where the Dispose method had to be hard-coded in a C# program. Otherwise the file used in an email will be "forever" locked and not even Process Manager was able to tell me who/what locked it. I had to use Unlocker Assistant to force delete the file, but I fear now I've left some allocated memory blocks on the server.

The code I am referring to is this:

MailMessage mail = new MailMessage();
mail.From = new MailAddress("reception@domain.com", "###");
mail.Subject = "Workplace Feedback Form";
Attachment file = new Attachment(uniqueFileName);
mail.Attachments.Add(file);
mail.IsBodyHtml = true;
mail.CC.Add("somebody@domain.com");
mail.Body = "Please open the attached Workplace Feedback form....";

//send it
SendMail(mail, fldEmail.ToString());

The above code left the file from uniqueFileName locked by the Attachment handle and I was not able to delete it and because this code ran from a client machine (not from the server itself), the handle to the file was impossible to find.

After I had forced a deletion the files, I found from another forum that I should have Disposed of the Attachment object.

So I added these lines of code after the email was sent ...

//dispose of the attachment handle to the file for emailing, 
//otherwise it won't allow the next line to work.
file.Dispose(); 

mail.Dispose(); //dispose of the email object itself, but not necessary really
File.Delete(uniqueFileName);  //delete the file 

Should I have wrapped this in a using statement instead?

And that's the crux of my question. When should we use Using and when should we use Dispose? I hope there is a clear distinction between the two which says if you do "X" then use this, else use that.

This When to Dispose? and this C# Dispose : when dispose and who dispose it do answer my question somewhat, but I am still confused about the "conditions" on when to use either.

Community
  • 1
  • 1
Fandango68
  • 4,461
  • 4
  • 39
  • 74
  • 1
    It may be of worth to note there are classes that I have ran into specifically for ftp in the Microsoft framework that do not have a dispose method that can be inherited when cast to another object type. I ran into one of these when I cast FtpWebResponse from a FtpWebRequest because the original object does not inherit IDisposable my transferred file was locked. So even know you set them in a using statement it does not do you any good. You may need to manually close them regardless as I did. I have a try catch statement simple not elegant to check file locking message me if you want it. – vikingben Mar 28 '14 at 02:16
  • I'll just have to cross that bridge when I come across it, but you are right and I'll keep this in mind. Thanks – Fandango68 Mar 28 '14 at 04:20

2 Answers2

7

using in C#:

using(MyDisposableType obj = new MyDisposableType())
{
  ...
}

is "syntactic sugar" (or short-hand notation) that is equivalent to

MyDisposableType obj = new MyDisposableType();
try {
  ...
} finally {
  obj.Dispose();
}

as described in http://msdn.microsoft.com/en-us//library/yh598w02.aspx

Igor
  • 15,833
  • 1
  • 27
  • 32
  • Simple answer. But @dstanley took it because his answer actually answered the situations when it's needed. Thank you – Fandango68 Mar 28 '14 at 04:19
4

Should I have wrapped this in a using statement instead?

Either that or put the main code in a try block and the Dispose in a finally block.

using just implements the Dispose pattern safely with less code. using will put Dispose in a finally block so that the object is disposed even if an exception is thrown. The way you have it now, if an exception is thrown, the objects will not be disposed and will instead be cleaned up when garbage collected.

I have never run across a case where I can't use using and must manually use a try/finally with Dispose().

So the choice is yours - you could just use Dispose in a finally block and it would likely be the same as if you used using.

D Stanley
  • 149,601
  • 11
  • 178
  • 240
  • +1. One case where you can't use `using` is long running operations on file. I.e. if you log events to a file during program execution you'd endup keeping file open for long time over lifetime of multiple methods. – Alexei Levenkov Mar 28 '14 at 02:06
  • @AlexeiLevenkov so you keep a reference to a disposable object and keep disposing/reopening it? – D Stanley Mar 28 '14 at 02:07
  • No, I mean you just keep file open for long time without disposing/closing. When you decide to switch to new log file/stop logging you dispose(close) the file. Or not just logging - some text editors may keep file open till user closes the file - again making creation and disposal be outside of scope of single method. – Alexei Levenkov Mar 28 '14 at 02:10
  • Thank you @DStanley. That's the answer. – Fandango68 Mar 28 '14 at 04:19