yyyy
yyyy

Reputation: 672

How does `typeof` operator get type argument in generic methods?

In Java, this code doesn't work:

public <T> void foo() { print(T.class); } // compile time error

Beacuse the generic type T is erased at runtime. To use T, I must use it as an argument, which will push String.class into stack

public <T> void foo(Class<T> T) { print(T); }
public void bar() { foo(String.class); }

But in C#, I can get type argument at runtime:

public void Foo<T>() { print(typeof(T)); }

How does it work? Does the compiler (or vm) automatically translate void Foo<T>() to void Foo(Type T)?


update:

I disassembled the bytecode and got something like:

ldtoken    !!T
call       System.Type System.Type::GetTypeFromHandle(System.RuntimeTypeHandle)

Since ldtoken is an instruction which "Convert metadata token to its runtime representation", it's clear that the runtime type of T is stored as metadata.

I guess each method has it's own "metadata table" (or something like that), so calling Foo<string>() and Foo<object>() will generate two "method handle" and two "metadata table", but share the same machine code. Is it?

Upvotes: 5

Views: 225

Answers (2)

Selman Gen&#231;
Selman Gen&#231;

Reputation: 101681

Does the compiler (or vm) automatically translate void Foo() to void Foo(Type T)?

No it doesn't. The body for generic methods is generated at runtime, on the fly. So, for example, when you supply T as int, this method is generated:

public void Foo<int>() { print(typeof(int)); }

This happens every time you pass a different type. But if you use the same type again the CLR will cache the previously generated method and execute it, instead of generating a new one.

Upvotes: 5

nilekirk
nilekirk

Reputation: 2383

In .NET, generics are not erased. The CLR implements generics all the way down to the byte code.

Upvotes: 0

Related Questions