I'm trying to write an operation that sums the hash codes for object
that "may" be a generic list. Obviously the code below does not
compile. But it gets the point across of what I'm trying to
accomplish. Is there a way to cast the object to a List<>?
public int GetHashCodeSum(Object obj)
{
int rv = 0;
if (obj.GetType().IsGenericType &&
obj.GetType().GetGenericTypeDefinition() == typeof(List<>))
{
foreach(Object item in ((List<>)obj).ToArray())
{
rv += item.GetHashCode();
}
First of all, for this specific case, you really should just use
IEnumerable (the non-generic one) - all collections are guaranteed to
implement it, as IEnumerable<T> extends IEnumerable. However,
sometimes you do really need that sort of thing - read on if you are
interested in a generic solution.
The most basic answer to your question: where isn't such a way,
because there are no objects of type List<> or compatible with it.
However, what you really want is to be able to just work with the
object. One obvious way is reflection - you can get the specific type
parameter for this object, and use it to call methods and handle
return values. Of course, this gets real messy real fast. A trick is
to separate the code that does generic processing into a separate
generic method; for example:
private int GetHashCodeTyped<T>(List<T> list)
{
int rv = 0;
foreach (var item in list) { rv += item.GetHashCode(); }
return rv;
}
Then, use reflection to invoke that method for various objects:
public int GetHashCodeSum(Object obj)
{
int rv = 0;
if (obj.GetType().IsGenericType &&
obj.GetType().GetGenericTypeDefinition() == typeof(List<>))
{
Type t = obj.GetType().GetGenericArguments()[0];
MethodInfo mdef = typeof(MyClass).GetMethod("GetHashCodeTyped",
BindingFlags.NonPublic);
MethodInfo m = mdef.MakeGenericMethod(t);
rv = (int)m.Invoke(this, new object[] { obj });
}
else
...
}
The advantage of this method is that no matter how complicated your
generic code is, it's still a few lines of reflection code to invoke
it, and from there you work with typed data.