Информация об изменениях

Сообщение Re: Сокрытие исключений от 22.09.2016 12:14

Изменено 22.09.2016 12:34 Sinix

Здравствуйте, Vasiliy2, Вы писали:

V>Где у меня ошибка в рассуждениях?


В общем случае всё правильно, проглатывать исключения без логирования не стоит.
Но у нас тут частный случай, в котором сообщить про "нишмогла" не так уж и критично.

Вот примерный сценарий использования:
using (var t = TempData.CreateFile())
{
  ... // полезный код
} // пытаемся грохнуть файл


Смотрим, какие исключения тут ловятся:

1. ArgumentException — в теории, его вообще не надо ловить, т.к. оно и бросаться-то не должно. Изначально я планировал, что путь проверяется в момент создания и за владение файлом отвечает сам код в TempData, но ув. Lexey решил сделать типы публичными и всю схему поломал Момент спорный, обсудим и починим.

Тем не менее, исключение было добавлено, т.к.

BRIAN GRUNKEMEYER Note that if your constructor throws an exception, the finalizer for your type will still run! So the finalizer and the Dispose(false) code path in your type must be prepared to handle an uninitialized state. Worse yet, if your app must deal with asynchronous exceptions such as ThreadAbortException or OutOfMemoryException, your finalizer may have to deal with partially initialized state if your constructor threw an exception halfway through! This surprising fact is usually pretty easy to deal with, but it may take you several years to realize it

(с)FDG


2. IOException и UnauthorizedAccessException могут быть брошены во куче причин.
Например, код внутри using открыл файл на чтение, бросил исключение и позабыл закрыть поток в finally.
Если в этом случае просто пробросить исключение "не смог удалить файл", то мы замаскируем исходное исключение.

Подробней — всё тот же FDG:

AVOID throwing an exception from within Dispose(bool) except under critical situations where the containing process has been corrupted (leaks, inconsistentshared state, etc.).
Users expect that a call to Dispose will not raise an exception. For example, consider the manual try-finally in this snippet:

TextReader tr = new StreamReader(File.OpenRead("foo.txt")); try {
// do some stuff
}
finally {
tr.Dispose();
// more stuff
}

If Dispose could raise an exception, further finally-block cleanup logic will not execute.


Вот как-то так. Если честно, этот код писался на автомате и проверки я ставил самые стандартные. Если есть идеи как сделать лучше — вэлкам!
Здравствуйте, Vasiliy2, Вы писали:

V>Где у меня ошибка в рассуждениях?


В общем случае всё правильно, проглатывать исключения без логирования не стоит.
Но у нас тут частный случай, в котором сообщить про "нишмогла" не так уж и критично.

Вот примерный сценарий использования:
using (var t = TempData.CreateFile())
{
  ... // полезный код
} // пытаемся грохнуть файл


Смотрим, какие исключения тут ловятся:

1. ArgumentException — в теории, его вообще не надо ловить, т.к. оно и бросаться-то не должно. Изначально я планировал, что путь проверяется в момент создания и за владение файлом отвечает сам код в TempData, но ув. Lexey решил сделать типы публичными и всю схему поломал Момент спорный, обсудим и починим.

Тем не менее, исключение было добавлено, т.к.

BRIAN GRUNKEMEYER Note that if your constructor throws an exception, the finalizer for your type will still run! So the finalizer and the Dispose(false) code path in your type must be prepared to handle an uninitialized state. Worse yet, if your app must deal with asynchronous exceptions such as ThreadAbortException or OutOfMemoryException, your finalizer may have to deal with partially initialized state if your constructor threw an exception halfway through! This surprising fact is usually pretty easy to deal with, but it may take you several years to realize it

(с)FDG


2. IOException и UnauthorizedAccessException могут быть брошены во куче причин.
Например, код внутри using открыл файл на чтение, бросил исключение и позабыл закрыть поток в finally.
Если в этом случае просто пробросить исключение "не смог удалить файл", то мы замаскируем исходное исключение.

Подробней — всё тот же FDG:

AVOID throwing an exception from within Dispose(bool) except under critical situations where the containing process has been corrupted (leaks, inconsistentshared state, etc.).
Users expect that a call to Dispose will not raise an exception. For example, consider the manual try-finally in this snippet:

TextReader tr = new StreamReader(File.OpenRead("foo.txt")); try {
// do some stuff
}
finally {
tr.Dispose();
// more stuff
}

If Dispose could raise an exception, further finally-block cleanup logic will not execute.


Вот как-то так. Если честно, этот код писался на автомате и проверки я ставил самые стандартные. Если есть идеи как сделать лучше — вэлкам!
UPD Нагло вру, тысяча извинений. Код в TempData изначально был написан AndrewVK, я его переписывал, подглядывая в наше аналогичное решение.
А вот его я уже писал на автомате