Reputation: 27220
I have a covariantly-safe generic class that wraps another. I wish to make it simple to get the most-derived type available of the instance at run-time:
public interface IReference<out T> { Type UnderlyingType { get; } }
public class Reference<T> : IReference<T> where T : class
{
public Type UnderlyingType => /*typeof(T)*/ this.GetType().GetGenericArguments()[0];
}
I'm pretty sure in the example above I can just use typeof(T)
to make the implementation above faster - but I want to make sure this doesn't lead to cases where a compile-time type is returned that is different from what the run-time type might have been.
For example, if someone goes:
IReference<object> weak = new Reference<string>()
IdentifyReference(weak);
void IdentifyReference<T>(IReference<T> unknown) where T : class {
Print(typeof(T));
Print(unknown.UnderlyingType);
}
I want the following output:
object
string
Upvotes: 1
Views: 190
Reputation: 271355
You can be sure that typeof(T)
in the UnderlyingType
property produces the runtime type, because of how polymorphism works.
There is simply not enough information at compile time for the compiler to figure out what unknown.UnderlyingType
is. Keep in mind that IReference
is an interface, so the compiler hasn't got the faintest idea of what concrete type unknown
is. Therefore, it doesn't even know that this particular implementation should be executed:
public Type UnderlyingType => typeof(T) /*this.GetType().GetGenericArguments()[0]*/;
As far as the compiler is concerned, it could be an implementation from Foo
, which just so happens to implement IReference<object>
.
Therefore, the expression typeof(T)
is evaluated at runtime, when runtime polymorphism (dynamic dispatch chooses the right implementation) occurs. The way polymorphism works causes the expression to always be evaluated in the context of the runtime type.
Upvotes: 1