You might see that a condition has been logically met, but the compiler does not "remember" this.
public static T GetNode<T>() where T : NodeBase
{
if (typeof(T) == typeof(SpecialNode)) // OK, you now know T is SpecialNode
{
// the compiler still insists on returning a T,
// and will not assume that MySpecialNode is a T
return MySpecialNode;
}
// ...
return default(T);
}
It's true what others have already said: you must cast MySpecialNode
: (T)(NodeBase)MySpecialNode
(which you can do safely, because you have already checked that T
is SpecialNode
).
It's easy to think of this as a shortcoming of the compiler; but this is just a mistake stemming from how obvious it seems that MySpecialNode
is a T
. Suppose I had a method like this:
public T Get<T>() {
if (typeof(T).FullName.Equals("System.Int32"))
return 5;
else
return default(T);
}
Should this compile? I should hope not; the compiler needs to guarantee that it's returning an object of type T
, and it can't be sure that 5
will meet that requirement just from some bizarre check that I the developer have performed. (Yes, I know that T
is int
, but I would not expect any reasonable compiler to determine that from a comparison of the System.Type.FullName
property.)
Checking if (typeof(T) == typeof(SpecialNode))
is really not so different from that.