implict type cast in generic method

后端 未结 7 1240
刺人心
刺人心 2021-01-19 09:47

why do I get a compiler error in the following code stating: Cannot implicty convert type SpecialNode to T even though T must derive from NodeBase as I defined

7条回答
  •  陌清茗
    陌清茗 (楼主)
    2021-01-19 10:18

    Ah, that moment you wish the language had some kinda static polymorphism. Type checking in a generic method is not very cool. This can be a better solution if your requirements let:

    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() where T : NodeBase, new()
    {
        return (T)new T().GetNode();
    }
    

    This suffer from a disadvantage that you have to expose a parameterless constructor. In case that's undesirable, may be a slightly better approach is to push the generic call one layer backward, and ask your static class itself to do the work for you. Changing static class definition to something like:

    public static T GetNode() where T : NodeBase
    {
        return ThisStaticClass.GetNode();
    }
    
    //in which case ThisStaticClass have awareness of 
    //parameterless new() constructor of T class, which still need not be good enough
    

    You can get it a bit more strongly typed by going one generic level deeper.

    public abstract class NodeBase where T : NodeBase
    {
        public abstract T GetNode();
    }
    
    public class SpecialNode : NodeBase
    {
        public override SpecialNode GetNode()
        {
            return ThisStaticClass.MySpecialNode;
        }
    }
    
    public class OtherSpecialNode : NodeBase
    {
        public override OtherSpecialNode GetNode()
        {
            return ThisStaticClass.MyOtherSpecialNode;
        }
    }
    
    //avoids cast
    public static T GetNode() where T : NodeBase, new()
    {
        return new T().GetNode();
    }
    

提交回复
热议问题