Andrew
Andrew

Reputation: 829

When and how is type determined for constrained generic types when type is implicit?

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

Answers (2)

BradleyDotNET
BradleyDotNET

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

TypeIA
TypeIA

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

Related Questions