Reputation: 22362
I want to be able to catch a WebFaultException<string>
as the most specific then a WebFaultException<T>
(T being any other type) as a more general case to handle. Is this possible?
try
{
// throw exception
}
catch (WebFaultException<string> e)
{
// handle more specific type
}
catch (WebFaultException<T> e)
{
// handle more general type
}
catch (Exception e)
{
}
Upvotes: 43
Views: 16394
Reputation: 13148
Use a non-generic base class. It's very often good practice anyway to have a non-generic base. You can push all non-generic data and functionality up into it as well, solving the problem of having lists of varied generic type.
Rather than (applies whether inheriting from Exception
or not):
sealed class MyClass<T> {
public T GenericProperty { get; set; }
public int NonGenericProperty { get; set; }
}
Do this:
// optionally abstract
class MyClass {
public int NonGenericProperty { get; set; }
}
sealed class MyClass<T> : MyClass {
public T GenericProperty { get; set; }
}
Upvotes: 0
Reputation: 3355
I personally abstract creation of exceptions to a generic class which is derived from Exception
.
https://net7mma.codeplex.com/SourceControl/latest#Common/Exception.cs
I have also defined an Interface IExceptionEx
to accommodate the derivation.
This gives you the opportunity to wrap exceptions like so...
try{ /*error prone logic*/ } catch (Exception ex)
{
Common.ExceptionExtensions.CreateAndRaiseException(this, "Could not resolve host from the given location. See InnerException.", ex);
}
Catching specific types then works like this...
catch (Common.Exception<RtspClient>)
{
throw;
}
catch (Common.Exception<SessionDescription>)
{
Common.ExceptionExtensions.CreateAndRaiseException(this, "Unable to describe media, Session Description Exception Occured.");
}
You can catch all derived with this:
catch (Common.Exception common) {}
Or every Exception with this
catch (Exception ex) {}
Upvotes: 0
Reputation: 81105
A few points not yet mentioned:
Using generic type parameters with exceptions seems like a nice ability, especially given that one set of constructors can be used for a whole family of exceptions. Unfortunately, it doesn't seem to work nearly as well as one would hope.
Upvotes: 2
Reputation: 4346
You can manage something similar by deriving your exception class from a common base
public class WebFaultException<T> : WebFaultException
{
public WebFaultException(T content) : base(content)
public T Content { get { return ObjContent; } }
}
public class WebFaultException
{
public WebFaultException(object content)
{
ObjContent = content;
}
public object ObjContent { get; private set; }
}
now you can catch WebFaultException
, or WebFaultException<string>
Upvotes: 1
Reputation: 8613
As other answers have mentioned; you cannot directly specify to catch every WebFaultException<T>
without either knowing the specified type argument, or catching it's base type instead.
However, if you were wanting to catch all WebFaultException
occurrences and handle the response differently based on what the generic type is, then you could simply catch the base type and use reflection to determine the type of the generic argument using Type.GetGenericArguments()
. Here is a simple catch
clause to show how you may go about doing it:
// ...
catch (FaultException ex)
{
Type exceptionType = ex.GetType();
if (exceptionType.IsGenericType)
{
// Find the type of the generic parameter
Type genericType = ex.GetType().GetGenericArguments().FirstOrDefault();
if (genericType != null)
{
// TODO: Handle the generic type.
}
}
}
If you want a more indepth example, I have uploaded a test program to demonstrate this to PasteBin. Feel free to take a look!
Upvotes: 17
Reputation: 21241
A generic type is a type in itself, there is no concept of the templated parameter at runtime, so WebFaultException is in no way related to WebFaultException.
If I were you I would create a non generic WebFaultException base, and derive your generic types from that.
Upvotes: 1
Reputation: 49609
Unfortunately this is not possible. You can use WebFaultException
's common nongeneric base class and then catch that and handle or rethrow the more specifc exceptions using reflection in that handler.
I'd recommend to not depend on generic type arguments in exception handling. Generics will always get in your way whenever you have to make decisions based on a type.
Upvotes: 3
Reputation: 6090
I've never thought of anything like this, so I got curious and did a little scratch pad implementation. First off, the following works:
public class WebFaultException : Exception
{
public WebFaultException() { }
public WebFaultException(string message) : base(message) { }
public WebFaultException(string message, Exception innerException) : base(message, innerException) { }
protected WebFaultException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) : base(info, context) { }
}
public class WebFaultException<T> : WebFaultException
{
public WebFaultException() { }
public WebFaultException(string message) : base(message) { }
public WebFaultException(string message, Exception innerException) : base(message, innerException) { }
protected WebFaultException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) : base(info, context) {}
}
As your exception definitions and then these tests both pass:
[TestMethod]
public void SpecificGeneric()
{
bool hitException = false;
try
{
throw new WebFaultException<string>();
}
catch(WebFaultException<string> e)
{
hitException = true;
}
Assert.IsTrue(hitException);
}
[TestMethod]
public void AnyGeneric()
{
bool hitException = false;
try
{
throw new WebFaultException<int>();
}
catch (WebFaultException<string> e)
{
hitException = false;
}
catch (WebFaultException e)
{
hitException = true;
}
Assert.IsTrue(hitException);
}
In terms of doing what you want specifically, there's a catch. In the code as you presented it, WebDefaultException<T>
is meaningless because you have provided no T. However, you can get around that (somewhat awkwardly) like this (another passing unit test):
[TestMethod]
public void CallingGenericMethod()
{
Assert.IsTrue(GenericExceptionMethod<int>());
}
private bool GenericExceptionMethod<T>()
{
bool hitException = false;
try
{
throw new WebFaultException<int>();
}
catch (WebFaultException<string> e)
{
hitException = false;
}
catch (WebFaultException<T> e)
{
hitException = true;
}
return hitException;
}
That is, if the method (or class) in which you're handling the exception has a generic parameter, you can actually catch WebFaultException<T>
. However, I would urge a word of caution that this is a very weird thing to do -- as a client of your method, I'm forced to pass in a type that will be used for nothing that I care about and is an internal implementation detail to you for some exception that you want to catch.
So, I'd say yes, possible. But also awkward at best and perhaps ill-advised.
Upvotes: 5