By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
434,573 Members | 903 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 434,573 IT Pros & Developers. It's quick & easy.

Inconsistence! .NET 2.0 Generics and Exceptions

P: n/a
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>.CatchInConstructo r();
}
}
}

/*
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.
*/
May 29 '06 #1
Share this Question
Share on Google+
1 Reply


P: n/a
Vladimir,
----------
The INCONSISTENCE is:

Exception "MyOwnException" thrown from constructor of "ThrowInConstructor",
somehow TURNS INTO "TargetInvocationException" and is NOT caught by
"catch(MyOwnException)" block!!!
----------


That's because

new T()

compiles to

Activator.CreateInstance<T>()

and that method is documented as throwing a TargetInvocationException
if the constructor throws.
Mattias

--
Mattias Sjögren [C# MVP] mattias @ mvps.org
http://www.msjogren.net/dotnet/ | http://www.dotnetinterop.com
Please reply only to the newsgroup.
May 29 '06 #2

This discussion thread is closed

Replies have been disabled for this discussion.