Type of implication in the general method

why do I get a compiler error in the following code: Cannot implicty convert type SpecialNode to Talthough T should be inferred from NodeBase, as I defined in the where clause, and even if SpecialNode is actually derived from NodeBase?

    public static T GetNode<T>() where T : NodeBase
    {
        if (typeof(T) == typeof(SpecialNode))
        {
            return ThisStaticClass.MySpecialNode; // <-- compiler error
        }
        if (typeof(T) == typeof(OtherSpecialNode))
        {
            return ThisStaticClass.MyOtherSpecialNode; // <-- compiler error
        }
        ...
        return default(T);
    }
+4
source share
7 answers

The compiler does not read your check ifto understand what Tshould be in this particular line SpecialNode.

First you need to specify NodeBase, for example:

return (T)(NodeBase)MySpecialNode;

You need to do the casting, because (as far as the compiler knows) it Tmay be MyOtherSpecialNode, and you cannot drop MyOtherSpecialNodeuntil MySpecialNode.

EDIT . You can do this with a single cast:

NodeBase retVal;

if (typeof(T) == typeof(SpecialNode))
    retVal = MySpecialNode;
else if (typeof(T) == typeof(OtherSpecialNode))
    retVal = MyOtherSpecialNode;

return (T)retVal;
+3

, , .

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);
}

, : MySpecialNode: (T)(NodeBase)MySpecialNode ( , , T SpecialNode).

; , , , MySpecialNode T. , :

public T Get<T>() {
    if (typeof(T).FullName.Equals("System.Int32"))
        return 5;
    else
        return default(T);
}

? , ; , T, , 5 , . (, I , T int, , - System.Type.FullName.)

if (typeof(T) == typeof(SpecialNode)) .

+3

, T, NodeBase, SpecialNode. if, , T SpecialNode.

, , T.

0

:

public static T GetNode<T>() where T : NodeBase
{
    T result;

    result = ThisStaticClass.MySpecialNode as T;
    if (result != null) return result;

    result = ThisStaticClass.MyOtherSpecialNode as T;
    if (result != null) return result;

    return default(T);
}

: , , , .

0

, , , - . . , :

public abstract class NodeBase
{
    public abstract NodeBase GetNode();
}

public class SpecialNode : NodeBase
{
    public override NodeBase GetNode()
    {
        return ThisStaticClass.MySpecialNode;
    }
}

public class OtherSpecialNode : NodeBase
{
    public override NodeBase GetNode()
    {
        return ThisStaticClass.MyOtherSpecialNode;
    }
}

//and in your generic method, just:
public static T GetNode<T>() where T : NodeBase, new()
{
    return (T)new T().GetNode();
}

, . , , , . - :

public static T GetNode<T>() where T : NodeBase
{
    return ThisStaticClass<T>.GetNode();
}

//in which case ThisStaticClass<T> have awareness of 
//parameterless new() constructor of T class, which still need not be good enough

, .

public abstract class NodeBase<T> where T : NodeBase<T>
{
    public abstract T GetNode();
}

public class SpecialNode : NodeBase<SpecialNode>
{
    public override SpecialNode GetNode()
    {
        return ThisStaticClass.MySpecialNode;
    }
}

public class OtherSpecialNode : NodeBase<OtherSpecialNode>
{
    public override OtherSpecialNode GetNode()
    {
        return ThisStaticClass.MyOtherSpecialNode;
    }
}

//avoids cast
public static T GetNode<T>() where T : NodeBase<T>, new()
{
    return new T().GetNode();
}
0

.

Generics < string, object >

return (T)MySpecialNode

if, , T

-1

:

return (T)MySpecialNode;

.NET?

-2

All Articles