Reputation: 829
When and how is the type of an object determined when using generics, specifically when the generic type is constrained to a class and the generic type is implicit?
To clarify, given the following code:
public class MyClass {}
public class MyClassA : MyClass {}
public static string GetMyClassTypeByGenericType<T>(T myClass)
where T: MyClass
{
return typeof(T).Name;
}
public static string GetMyClassTypeByObjectType<T>(T myClass)
where T: MyClass
{
return myClass.GetType().Name;
}
MyClassA myA = new MyClassA ();
GetMyClassTypeByGenericType(myA); // Result: "MyClassA"
GetMyClassTypeByObjectType(myA); // Result: "MyClassA"
MyClass myClass = myA;
GetMyClassTypeByGenericType(myClass); // Result: "MyClass"
GetMyClassTypeByObjectType(myClass); // Result: "MyClassA"
Why does the call GetMyClassTypeByGenericType(myClass)
return the name of the base class, not the derived class? I'm guessing the call resolves to GetMyClassTypeByGenericType<MyClass>(myClass)
implicitly based on the declared type of the variable myClass
, not the actual type.
Basically, I would just like to know what's going on under the hood with generics concerning how type is determined.
Here is a fiddle for the code: https://dotnetfiddle.net/pCj08M
Upvotes: 2
Views: 140
Reputation: 61379
Generic type resolution is all compile time (which is why you cant stuff a Type
variable in a generic type parameter without reflection, which isn't really what we're talking about there).
Hence, when its given a variable type MyClassA
, that's what its going to use. Similarly for MyClass
even if the actual object is a derived type. For example, if you held it in an object
reference then the first call would print System.Object
.
On the other hand GetType
is run time, so it gets the actual type of the object no matter what the type of the variable holding it is.
Upvotes: 2
Reputation: 17258
Generic type construction, the process of resolving the actual types of each generic type parameter, is always performed at compile time in C# (unless, of course, you're using the Reflection API to construct a generic type at runtime).
In your example, the compiler is inferring the type T
based on the static type of the argument passed to the method. myClass
's static type is exactly what you declared it to be: MyClass
. So when you examine T
in the generic method you find that T == typeof(MyClass)
.
On the other hand, when you call .GetType()
on the object passed in, you're making a runtime query of the dynamic (actual runtime) type of the object, which of course is what you constructed, MyClassA
.
Upvotes: 1