What is the appropriate exception to throw for an Object being passed in and needing to be cast to the generic parameter?
public IPredefinedInterface
{
void DoSomething(Object obj);
}
public class MyClass<T> : IPredefinedInterface
{
public void DoSomething(Object obj)
{
if (!(obj is T)) throw new ???
SomeOtherFunc((T)obj);
}
}
Not sure what the appropriate exception he开发者_运维百科re is... ArgumentException, InvalidCastException, etc?
It's a problem with the argument, so ArgumentException
. You haven't actually done the cast, so InvalidCastException
is not appropriate.
Consider the example of IList
, which supports Add
operations using type object
. When implemented by the generic List<T>
, you get an ArgumentException
for invalid types.
var list = new List<int>();
var ilist = list as IList;
ilist.Add("A");
Result:
ArgumentException: The value "A" is not of type "System.Int32" and cannot be used in this generic collection.Parameter name: value
In examples like this, I might tend to follow the precedents set by BCL classes unless there are compelling arguments against it.
I would consider making a generic interface:
public interface IPredefinedInterface<T>
{
void DoSomething(T obj)
}
Then implement like so:
public clas MyClass<T> : IPredefinedInterface<T>
{
public void DoSomething(T obj)
{
// It's now always T, eliminating the need for an exception
}
}
If you can't go with that pattern (because you want to be able to pass any type in), then I would suggest going with a context specific exception for that class:
public class InvalidMyClassInputException : ApplicationException
{
public InvalidMyClassInputException(object obj)
: base("An invalid call to DoSomething was made with object of type: " + obj.GetType().Name)
{
}
}
Whenever a cast causes an exception (or if something cannot be cast), a InvalidCastException is appropriate.
However, re-architecting your code may be a better solution, and allow compile-time checking:
public IPredefinedInterface<T>
{
void DoSomething(T obj);
}
public class MyClass<T> : IPredefinedInterface<T>
{
public void DoSomething(T obj)
{
SomeOtherFunc((T)obj);
}
}
Then you don't even need to check because the environment and/ or compiler is doing it for you, which lets your code be much more simple.
精彩评论