Когда использовать Dispose или когда использовать Using

Недавно я столкнулся с ситуацией, когда метод Dispose пришлось жестко запрограммировать в программе на C#. В противном случае файл, используемый в электронном письме, будет заблокирован «навсегда», и даже Process Manager не сможет сказать мне, кто/что заблокировало его. Мне пришлось использовать Unlocker Assistant, чтобы принудительно удалить файл, но я боюсь, что теперь я оставил некоторые выделенные блоки памяти на сервере.

Код, который я имею в виду, таков:

MailMessage mail = new MailMessage();
mail.From = new MailAddress("[email protected]", "###");
mail.Subject = "Workplace Feedback Form";
Attachment file = new Attachment(uniqueFileName);
mail.Attachments.Add(file);
mail.IsBodyHtml = true;
mail.CC.Add("[email protected]");
mail.Body = "Please open the attached Workplace Feedback form....";

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

Приведенный выше код оставил файл из uniqueFileName заблокированным дескриптором вложения, и я не смог его удалить, а поскольку этот код запускался с клиентской машины (а не с самого сервера), дескриптор файла было невозможно найти.

После того, как я принудительно удалил файлы, я обнаружил на другом форуме, что должен был удалить объект вложения.

Поэтому я добавил эти строки кода после того, как электронное письмо было отправлено...

//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 

Должен ли я вместо этого обернуть это в оператор using?

И в этом суть моего вопроса. Когда мы должны использовать Using и когда мы должны использовать Dispose? Я надеюсь, что между ними есть четкое различие, которое говорит, что если вы делаете «X», то используйте это, иначе используйте это.

Это Когда удалять? и это C# Dispose : когда распоряжаться и кто его распоряжается несколько отвечает на мой вопрос, но я все еще не понимаю "условий" о том, когда их использовать.


person Fandango68    schedule 28.03.2014    source источник
comment
Возможно, стоит отметить, что есть классы, с которыми я столкнулся специально для ftp в среде Microsoft, у которых нет метода dispose, который может быть унаследован при приведении к другому типу объекта. Я столкнулся с одним из них, когда вызывал FtpWebResponse из FtpWebRequest, потому что исходный объект не наследует IDisposable, и мой переданный файл был заблокирован. Поэтому даже зная, что вы установили их в операторе использования, это не принесет вам никакой пользы. Возможно, вам придется закрыть их вручную, как это сделал я. У меня есть оператор try catch, простой, а не элегантный, чтобы проверить сообщение о блокировке файла, если вы этого хотите.   -  person vikingben    schedule 28.03.2014
comment
Мне просто нужно будет пересечь этот мост, когда я его найду, но ты прав, и я буду иметь это в виду. Спасибо   -  person Fandango68    schedule 28.03.2014


Ответы (2)


Должен ли я вместо этого обернуть это в оператор using?

Либо так, либо поместите основной код в блок try, а Dispose в блок finally.

using просто безопасно реализует шаблон Dispose с меньшим количеством кода. using поместит Dispose в блок finally, чтобы объект удалялся, даже если выдается исключение. Как у вас сейчас, если выдается исключение, объекты не будут удалены, а вместо этого будут очищены при сборке мусора.

Я никогда не сталкивался со случаем, когда я не могу использовать using и должен вручную использовать try/finally с Dispose().

Так что выбор за вами — вы можете просто использовать Dispose в блоке finally, и это, вероятно, будет таким же, как если бы вы использовали using.

person D Stanley    schedule 28.03.2014
comment
+1. Один из случаев, когда вы не можете использовать using, — это длительные операции над файлом. т.е. если вы регистрируете события в файле во время выполнения программы, вы в конечном итоге будете держать файл открытым в течение длительного времени в течение всего срока службы нескольких методов. - person Alexei Levenkov; 28.03.2014
comment
@AlexeiLevenkov, значит, вы сохраняете ссылку на одноразовый объект и продолжаете утилизировать / повторно открывать его? - person D Stanley; 28.03.2014
comment
Нет, я имею в виду, что вы просто держите файл открытым в течение длительного времени, не удаляя/закрывая. Когда вы решите переключиться на новый файл журнала / прекратить ведение журнала, вы удаляете (закрываете) файл. Или не просто ведение журнала - некоторые текстовые редакторы могут держать файл открытым до тех пор, пока пользователь не закроет файл - опять же создание и удаление выходят за рамки одного метода. - person Alexei Levenkov; 28.03.2014
comment
Спасибо @DStanley. Это ответ. - person Fandango68; 28.03.2014

using in C#:

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

является «синтаксическим сахаром» (или сокращенной записью), который эквивалентен

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

как описано в http://msdn.microsoft.com/en-us//library/yh598w02.aspx

person Igor    schedule 28.03.2014
comment
Простой ответ. Но @dstanley принял это, потому что его ответ действительно отвечал ситуациям, когда это необходимо. Спасибо - person Fandango68; 28.03.2014