V
Vladimir Shiryaev
Hello!
Exception handling in generics seems to be a bit inconsistent to me.
Imagine, I have "MyOwnException" class derived from "ApplicationException".
I also have two classes "ThrowInConstructor" and "ThrowInFoo". First one
throws "MyOwnException" in constructor, second one in "Foo()" method. There
is a "GenericCatch" generics class able to accept "ThrowInConstructor" and
"ThrowInFoo" as type parameter "<T>". There are two methods in
"GenericCatch": "CatchInFoo()" and "CatchInConstructor()". Each method has a
"try{}catch(MyOwnException)" block. Object of type "T" created inside try
block and "Foo()" method is called for it.
----------
The INCONSISTENCE is:
Exception "MyOwnException" thrown from constructor of "ThrowInConstructor",
somehow TURNS INTO "TargetInvocationException" and is NOT caught by
"catch(MyOwnException)" block!!!
----------
There are four possible choices:
1. "catch" block is placed somewhere in class without generics.
1.1 Exception "MyOwnException" thrown in ordinary "Foo()" method falls into
"catch(MyOwnException)" block.
1.2 Exception "MyOwnException" thrown in constructor falls into
"catch(MyOwnException)" block.
2. "catch" block is placed somewhere in class WITH generics.
2.1 Exception "MyOwnException" thrown in ordinary "Foo()" method falls into
"catch(MyOwnException)" block.
2.2 Exception "MyOwnException" thrown in constructor turn into
"TargetInvocationException" (with "InnerException" property set to
"MyOwnException") and DOES NOT fall into "catch(MyOwnException)" block.
Any ideas WHY ??? May be I miss something ???
P.S.
You can find an example (simple C# console application) that illustrates
this issue below.
Thanks,
Vladimir
//
// .NET Framework 2.0
// Microsoft Visual Studio 2005
// C# console application
//
using System;
using System.Collections.Generic;
using System.Text;
using System.Reflection;
namespace generic.exception
{
interface IFoo
{
void Foo();
}
class MyOwnException : ApplicationException
{
public MyOwnException( string message ) : base( message ) {}
}
class GenericCatch< T > where T : class, IFoo, new()
{
public static void CatchInFoo()
{
try
{
T t = new T();
t.Foo();
}
catch ( MyOwnException e )
{
Console.WriteLine( "GenericCatch.CatchInFoo catch (
MyOwnException )" );
Console.WriteLine( "e.Message: " + e.Message );
}
}
public static T CatchInConstructor()
{
try
{
T t = new T();
t.Foo();
}
catch ( MyOwnException e )
{
Console.WriteLine( "GenericCatch.CatchInConstructor catch (
MyOwnException )" );
Console.WriteLine( "e.Message: " + e.Message );
}
catch ( ApplicationException e )
{
Console.WriteLine( "GenericCatch.CatchInConstructor catch (
ApplicationException )" );
Console.WriteLine( "Exception of type: " + e.GetType().ToString() );
Console.WriteLine( "e.Message: " + e.Message );
}
return null;
}
}
class ThrowInConstructor : IFoo
{
public ThrowInConstructor()
{
Console.WriteLine( "ThrowInConstructor.Constructor() throw new
MyOwnException()" );
throw new MyOwnException( "MyOwnException in Constructor()" );
}
public void Foo()
{
}
}
class ThrowInFoo : IFoo
{
public ThrowInFoo()
{
}
public void Foo()
{
Console.WriteLine( "ThrowInFoo.Foo() throw new MyOwnException()" );
throw new MyOwnException( "MyOwnException in Foo()" );
}
}
class Program
{
static void Main( string[] args )
{
try
{
Console.WriteLine( "Call ThrowInConstructor outside of generics" );
ThrowInConstructor t = new ThrowInConstructor();
}
catch( MyOwnException e )
{
Console.WriteLine( "outside of generics catch ( MyOwnException )" );
Console.WriteLine( "e.Message: " + e.Message );
}
Console.WriteLine();
GenericCatch<ThrowInFoo>.CatchInFoo();
Console.WriteLine();
GenericCatch<ThrowInConstructor>.CatchInConstructor();
}
}
}
/*
Console application output:
----------
Call ThrowInConstructor outside of generics
ThrowInConstructor.Constructor() throw new MyOwnException()
outside of generics catch ( MyOwnException )
e.Message: MyOwnException in Constructor()
ThrowInFoo.Foo() throw new MyOwnException()
GenericCatch.CatchInFoo catch ( MyOwnException )
e.Message: MyOwnException in Foo()
ThrowInConstructor.Constructor() throw new MyOwnException()
GenericCatch.CatchInConstructor catch ( ApplicationException )
Exception of type: System.Reflection.TargetInvocationException
e.Message: Exception has been thrown by the target of an invocation.
*/
Exception handling in generics seems to be a bit inconsistent to me.
Imagine, I have "MyOwnException" class derived from "ApplicationException".
I also have two classes "ThrowInConstructor" and "ThrowInFoo". First one
throws "MyOwnException" in constructor, second one in "Foo()" method. There
is a "GenericCatch" generics class able to accept "ThrowInConstructor" and
"ThrowInFoo" as type parameter "<T>". There are two methods in
"GenericCatch": "CatchInFoo()" and "CatchInConstructor()". Each method has a
"try{}catch(MyOwnException)" block. Object of type "T" created inside try
block and "Foo()" method is called for it.
----------
The INCONSISTENCE is:
Exception "MyOwnException" thrown from constructor of "ThrowInConstructor",
somehow TURNS INTO "TargetInvocationException" and is NOT caught by
"catch(MyOwnException)" block!!!
----------
There are four possible choices:
1. "catch" block is placed somewhere in class without generics.
1.1 Exception "MyOwnException" thrown in ordinary "Foo()" method falls into
"catch(MyOwnException)" block.
1.2 Exception "MyOwnException" thrown in constructor falls into
"catch(MyOwnException)" block.
2. "catch" block is placed somewhere in class WITH generics.
2.1 Exception "MyOwnException" thrown in ordinary "Foo()" method falls into
"catch(MyOwnException)" block.
2.2 Exception "MyOwnException" thrown in constructor turn into
"TargetInvocationException" (with "InnerException" property set to
"MyOwnException") and DOES NOT fall into "catch(MyOwnException)" block.
Any ideas WHY ??? May be I miss something ???
P.S.
You can find an example (simple C# console application) that illustrates
this issue below.
Thanks,
Vladimir
//
// .NET Framework 2.0
// Microsoft Visual Studio 2005
// C# console application
//
using System;
using System.Collections.Generic;
using System.Text;
using System.Reflection;
namespace generic.exception
{
interface IFoo
{
void Foo();
}
class MyOwnException : ApplicationException
{
public MyOwnException( string message ) : base( message ) {}
}
class GenericCatch< T > where T : class, IFoo, new()
{
public static void CatchInFoo()
{
try
{
T t = new T();
t.Foo();
}
catch ( MyOwnException e )
{
Console.WriteLine( "GenericCatch.CatchInFoo catch (
MyOwnException )" );
Console.WriteLine( "e.Message: " + e.Message );
}
}
public static T CatchInConstructor()
{
try
{
T t = new T();
t.Foo();
}
catch ( MyOwnException e )
{
Console.WriteLine( "GenericCatch.CatchInConstructor catch (
MyOwnException )" );
Console.WriteLine( "e.Message: " + e.Message );
}
catch ( ApplicationException e )
{
Console.WriteLine( "GenericCatch.CatchInConstructor catch (
ApplicationException )" );
Console.WriteLine( "Exception of type: " + e.GetType().ToString() );
Console.WriteLine( "e.Message: " + e.Message );
}
return null;
}
}
class ThrowInConstructor : IFoo
{
public ThrowInConstructor()
{
Console.WriteLine( "ThrowInConstructor.Constructor() throw new
MyOwnException()" );
throw new MyOwnException( "MyOwnException in Constructor()" );
}
public void Foo()
{
}
}
class ThrowInFoo : IFoo
{
public ThrowInFoo()
{
}
public void Foo()
{
Console.WriteLine( "ThrowInFoo.Foo() throw new MyOwnException()" );
throw new MyOwnException( "MyOwnException in Foo()" );
}
}
class Program
{
static void Main( string[] args )
{
try
{
Console.WriteLine( "Call ThrowInConstructor outside of generics" );
ThrowInConstructor t = new ThrowInConstructor();
}
catch( MyOwnException e )
{
Console.WriteLine( "outside of generics catch ( MyOwnException )" );
Console.WriteLine( "e.Message: " + e.Message );
}
Console.WriteLine();
GenericCatch<ThrowInFoo>.CatchInFoo();
Console.WriteLine();
GenericCatch<ThrowInConstructor>.CatchInConstructor();
}
}
}
/*
Console application output:
----------
Call ThrowInConstructor outside of generics
ThrowInConstructor.Constructor() throw new MyOwnException()
outside of generics catch ( MyOwnException )
e.Message: MyOwnException in Constructor()
ThrowInFoo.Foo() throw new MyOwnException()
GenericCatch.CatchInFoo catch ( MyOwnException )
e.Message: MyOwnException in Foo()
ThrowInConstructor.Constructor() throw new MyOwnException()
GenericCatch.CatchInConstructor catch ( ApplicationException )
Exception of type: System.Reflection.TargetInvocationException
e.Message: Exception has been thrown by the target of an invocation.
*/