Вчера в комментариях заметки "Отложенные действия в C#" был задан вопрос про исключения. В нем подразумевалась необходимость определять в методе Dispose() нормально ли завершился код блока using. При этом сам метод вызывается до передачи управления блоку catch. Так есть ли решение?
Логично предположить, что раз эта заметка опубликована, то и решение есть. Поэтому сразу посмотрим его на примере простой реализации IDisposable.
using System;
using System.Runtime.InteropServices;
/// <summary>Test class.</summary>
public class DisposableObject : IDisposable
{
/// <summary>IDisposable implementation that checks for an exception.</summary>
void IDisposable.Dispose()
{
// Check for an exception
if (Marshal.GetExceptionCode() != 0) {
Console.WriteLine("Dispose() > Exception detected!");
return;
}
Console.WriteLine("Dispose() > Completed successfully!");
}
/// <summary>Throwing demo exception.</summary>
public void ExceptionTest()
{
Console.WriteLine("IDisposableObject.ExceptionTest() > throwing exception ...");
throw new NotImplementedException();
}
}
Для определения исключения используется метод класса Marshal
public static int GetExceptionCode();
Он возвращает код типа исключения, который при нормальном выполнении программы будет равен нулю. Остальные значения будем считать просто признаком наличия исключения.
Для проверки создадим простое консольное приложение:
using System;
class Program
{
static void Main(string[] args)
{
try {
using (DisposableObject obj = new DisposableObject()) {
throw new InvalidCastException();
// obj.ExceptionTest();
}
}
catch (Exception ex) {
Console.WriteLine("try-catch > Exception caught!\n\n{0}", ex.ToString());
}
Console.ReadKey(true);
}
}
Комментарии тут не требуются.
Исходный код (C#, Visual Studio 2010):
IDisposableExceptionDemo.zip (8.74 kb)