How generic methods gets instantiated in C#?
Asked Answered
C

3

6

Suppose I've a generic method as:

void Fun<T>(FunArg arg) {}

Are this.Fun<Feature> and this.Fun<Category> different instantiations of the generic method?

In general, how does the generic method get instantiated? Different generic argument produces different method, or same method along with different metadata which is used at runtime?

Please support your answer with some quote(s) from the language specification.

Also, suppose I did these:

client.SomeEvent += this.Fun<Feature>;   //line1
client.SomeEvent += this.Fun<Category>;  //line2
client.SomeEvent += this.Fun<Result>;    //line3

then later on,

client.SomeEvent -= this.Fun<Feature>;   //lineX

Does the lineX undo the thing which I did at line1? Or it depends on somethig else also?

Claudicant answered 23/4, 2012 at 10:40 Comment(9)
That's not valid code to start with. You can't use a method group conversion as the target of a var declaration. Present valid code, and we can give a better answer.Procyon
@JonSkeet: Removed that part.Claudicant
So at this point, what exactly do you mean by an "instantiation"? The clearer you can be in your question, the clearer your answer can be.Procyon
@JonSkeet: By instantiation, I meant different method at runtime. Two instantiations of the generic method means two different and separate methods at runtime which doesn't share anything.Claudicant
@Nawaz re your update; yes lineX creates a new delegate instance using Fun<Feature> (a specific, known-T, method); then delegate subtraction applies, which (because it is the same MethodInfo and same instance) cancels out the first Fun<Feature> in the delegate list, leaving Fun<Category> and Fun<Result>Cousins
@Nawaz "two different methods at runtime which doesn't share anything" is tricky.... each T is a separate MethodInfo, but there could still be some "sharing" (i.e. JIT sharing) - and they certainly share the same generic declaration.Cousins
@Nawaz: That's still not exact. Your update shows delegate objects - we can answer about that in particular, but if you mean more generally, you'd need to be more specific in your question.Procyon
@JonSkeet: I don't know how to ask that. I don't know much C# terminologies and their meanings. Anyway, let me try again: I basically I want to know if I can assume that Fun<Feature>() is different from Fun<Category>() in the same way as FunFeature() is different from FunCategory(). Can a C# programmer (not the compiler write) assume that?Claudicant
@Nawaz: For delegates, you can absolutely assume that you'll have different instances.Procyon
F
4

It depends on the types involved.

For all the reference types (ie. classes), one method will be JITted to handle them all.

For all the value types (ie. structs), one method per type will be JITted.

So the information in the question is not detailed enough to answer, if Feature and Category are reference types, then yes, one method will be JITted for them. If one of them, or both, are value types, one method per value type will be JITted.

Note my use of the word JITted here. In the assembly compiled, there will be only one method, but at runtime, the JITter will create actual implementations of the generic methods according to the above rules.

Pop Quiz: What happens if you use NGEN on an assembly with generic types/methods? (hint: not what you think)

Fairminded answered 23/4, 2012 at 10:46 Comment(0)
C
5

They all share a method definition, but at runtime they are different MethodInfo - because the generic type arguments define a generic method.

Supporting illustration:

    Action<FunArg> a1 = Fun<X>;
    Action<FunArg> a2 = Fun<Y>;
    Action<FunArg> a3 = Fun<Y>;
    Console.WriteLine(a1.Method == a2.Method); // false
    Console.WriteLine(a3.Method == a2.Method); // true

At the JIT level, it is more complex; any reference-type parameters will share an implementation, as a reference is a reference is a reference (noting that all such T must satisfy any constraints in advance). If there are value-type T, then every combination of generic type arguments gets a separate implementation at runtime, since each requires a different final implementation.

Cousins answered 23/4, 2012 at 10:46 Comment(3)
Isn't it simple at the IL level, but complex at the native (JIT-compiled) level?Procyon
I updated my question with more queries. Please that as well:-)Claudicant
@Nawaz answered via a commentCousins
F
4

It depends on the types involved.

For all the reference types (ie. classes), one method will be JITted to handle them all.

For all the value types (ie. structs), one method per type will be JITted.

So the information in the question is not detailed enough to answer, if Feature and Category are reference types, then yes, one method will be JITted for them. If one of them, or both, are value types, one method per value type will be JITted.

Note my use of the word JITted here. In the assembly compiled, there will be only one method, but at runtime, the JITter will create actual implementations of the generic methods according to the above rules.

Pop Quiz: What happens if you use NGEN on an assembly with generic types/methods? (hint: not what you think)

Fairminded answered 23/4, 2012 at 10:46 Comment(0)
P
0

Yes, they will become two separate methods.

Pierre answered 23/4, 2012 at 10:42 Comment(2)
Do you have any sources for this?Manx
I may have to delete this answer by the way, because I wasn't looking too closely at the question.Pierre

© 2022 - 2024 — McMap. All rights reserved.