In MSDN, such methods are called non-generic methods of the generalized class, which is no better than my wording in the question. In the specification, this option is also not considered separately. Ok, since no matter where it’s written specifically, we’ll ask the CLR itself, in the end, it’s up to her to do everything we’ve written.
So let's start with the class declaration.
.class public auto ansi beforefieldinit ConsoleApplication.SomeClass`1<T>
An interesting point: `1 - the numbers after the apostrophe mean the number of type parameters, but the main task of this increase is to expand the class name. Thus, we can have two classes with the same name and a different number of generic parameters, including a non-generic class without parameters.
Method declarations (body omitted, since it does not matter in this case):
Not a generic method
.method public hidebysig instance void DoSomething ( int32 x //тип указан явно ) cil managed
Explicitly generalized method
.method public hidebysig instance void DoSomething<U> ( !!U x //обратите внимание на два восклицательных знака ) cil managed
Two exclamation marks tell JIT what specific type to look for in the generalizing parameters of the method.
Non-generic method with a generic class type parameter
.method public hidebysig instance void DoSomething ( !T x //тут только один восклицательный знак ) cil managed
One exclamation mark tells JIT that a specific type should be searched for in the class generalizing parameters.
Ok, already something, now let's take a look at how these methods are invoked:
Not a generic method
call instance void class ConsoleApplication.SomeClass`1<int32>::DoSomething(int32)
the type of the parameter is explicit
Explicitly generalized method
call instance void class ConsoleApplication.SomeClass`1<int32>::DoSomething<int32>(!!0)
the type of the parameter is indicated by a reference to the parameter with index 0 in the list of generalizing method parameters
Non-generic method with a generic class type parameter
call instance void class ConsoleApplication.SomeClass`1<int32>::DoSomething(!0)
the type of the parameter is indicated by a reference to the parameter with index 0 in the list of generalizing parameters of the class
It turns out that in the current implementation we have two types of generalized methods - explicit and implicit. In both cases, the JIT will need additional steps when compiling these methods to resolve types, since in both cases, the call indicates only a reference to the element of the list of generalizing parameters.
Total for a specific implementation of the compiler / JIT / VM:
There are two types of methods - generalized and not generalized .
Generalized methods can be generalized explicitly and implicitly .
Priority when choosing an overloaded method with other things being equal:
- not generalized
- implicitly generalized
- clearly generalized
This information can be found in the specification, but only indirectly, there are no direct references, apparently hoping for the logic of the readers.
PS: If there is another explanation, I will read it with pleasure in your answer.