Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Recover a "lost" type parameter

Tags:

c#

generics

Basically, my question is: Is there some way to "recover" a type parameter that was lost by upcast to a non-generic base type, e.g., Object. Here is an example of what I mean:

Consider I have received an Object l from a library and I know that l is an IList<T>, but I do not know the T (but I do know that it is a reference type, no value type). However, the exact type of T is not important, because all I want to do is to pass l to a generic method:

void doSomethingWithList<T>(IList<T> l){ ... }

However, I cannot do that, since I do not know to which type to cast l, i.e., I would like to do the following:

doSomethingWithList((IList<>)l);

I want to tell the compiler that l is an IList and it should call the method and bind the unknown type parameter to its parameter T. But it doesn't work like this. Do I have any options? Can I somehow pass an object for which I "lost" the type parameter to a generic method?

like image 929
gexicide Avatar asked Jul 21 '26 14:07

gexicide


2 Answers

You can do it using reflection:

var interfaceType = l.GetType().GetInterface("System.Collections.Generic.IList`1");
var itemType = interfaceType.GetGenericArguments()[0]; // This is your T
var method = this.GetType().GetMethod("doSomethingWithList").MakeGenericMethod(itemType);
method.Invoke(this, new object[] { l });

But if you can, it's probably better to change doSomethingWithList to accept a non-generic list...

like image 96
Thomas Levesque Avatar answered Jul 23 '26 10:07

Thomas Levesque


If you know it's safe, the simplest solution is to use dynamic:

doSomethingWithList((dynamic)l);

Otherwise you could check that l implements IList<T> for some T and call the method through reflection:

var listType = l.GetType().GetInterfaces().FirstOrDefault(i => i.IsGenericType && i.GetGenericTypeDefinition() == typeof(IList<>));
if (listType != null)
{
    Type elementType = listType.GetGenericArguments()[0];
    var method = this.GetType().GetMethod("doSomethingWithList").MakeGenericMethod(elementType);
    method.Invoke(this, new object[] { l });
}
like image 31
Lee Avatar answered Jul 23 '26 09:07

Lee



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!