Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

.NET bug: ldtoken of an instantiated generic method

Tags:

.net

generics

cil

I'm trying to get the ldtoken IL method to load a generic instantiation of a generic method within a generic class (say, List.ConvertAll<TOutput>):

ldtoken method instance
    class [mscorlib]System.Collections.Generic.List`1<!!0> 
    [mscorlib]System.Collections.Generic.List`1::ConvertAll<string>(
        class [mscorlib]System.Converter`2<!0,!!0>)

This results in an exception:

Unhandled Exception: System.TypeLoadException: Could not load type 'System.Collections.Generic.List`1' from assembly 'TestAssembly, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null'.

It's looking in my test assembly for System.Collections.Generic.List, even though it's explicitly declared in mscorlib!

However, loading the uninstantiated method token works:

ldtoken method instance
    class [mscorlib]System.Collections.Generic.List`1<!!0> 
    [mscorlib]System.Collections.Generic.List`1::ConvertAll<[1]>(
        class [mscorlib]System.Converter`2<!0,!!0>)

A generic method in a non-generic class works:

ldtoken method void [mscorlib]System.Array::Sort<object>(!!0[])
ldtoken method void [mscorlib]System.Array::Sort<[1]>(!!0[])

What's going on? Is this a bug in .NET? (I've replicated it on the v2 and v4 CLR)

like image 904
thecoop Avatar asked Dec 04 '25 16:12

thecoop


1 Answers

As I mentioned in a comment, I think you need to instantiate the generic type (i.e. there is no such type as System.Collections.Generic.List`1 - just System.Collections.Generic.List`1<object>, etc.).

By playing around with System.Reflection.Emit, it looks like it's possible to use ldtoken with an instantiated or uninstantiated method on an instantiated generic type:

ldtoken method instance 
    class [mscorlib]System.Collections.Generic.List`1<!!0> 
    class [mscorlib]System.Collections.Generic.List`1<object>::ConvertAll<[1]>(
        class [mscorlib]System.Converter`2<!0,!!0>)
ldtoken method instance 
    class [mscorlib]System.Collections.Generic.List`1<!!0> 
    class [mscorlib]System.Collections.Generic.List`1<object>::ConvertAll<string>(
        class [mscorlib]System.Converter`2<!0,!!0>)

but not with an uninstantiated generic type. Partition II, section 9.4 of the ECMA CLI spec states that

The CLI does not support partial instantiation of generic types. And generic types shall not appear uninstantiated anywhere in metadata signature blobs.

so perhaps this isn't surprising - there doesn't seem to be any way to use ldtoken with the equivalent of typeof(List<>).GetMethod("ConvertAll").

like image 184
kvb Avatar answered Dec 06 '25 05:12

kvb