【问题标题】:Inherited Generics Constructor C#继承的泛型构造函数 C#
【发布时间】:2012-02-08 15:15:27
【问题描述】:

您好,我正在尝试制作一个通用树节点。这是抽象的泛型类

public abstract class TreeNode<T>
{
    protected List<TreeNode<T>> _childNodes = new List<TreeNode<T>>();
    protected TreeNode<T> ParentNode;

    public T ObjectData { get; set; }

    public TreeNode( TreeNode<T> parent, T data)
    {
        ParentNode = parent;
        ObjectData = data;
    }    
}

它有一个伴随界面

interface TreeNodeOperations<T>
{
    //Adds child to tree node
    public abstract void AddChild<T>(T child);
    //Performs N-Tree search
    public abstract TreeNode<T> SeachChild<T>(T child);
}

我想要做的是继承这两个:

public class FHXTreeNode<T>: TreeNode<T>, TreeNodeOperations<T> where T : ParserObject
{
    public FHXTreeNode(FHXTreeNode<T> parent, T data) ---> # **ERROR** #
    {
        ParentNode = parent;
        ObjectData = data;
    }

    //Adds child to tree node
    public override FHXTreeNode<T> AddChild<ParserObject>(T childData)
    {
        FHXTreeNode<T> child = new FHXTreeNode<T>(this, childData);

        //_childNodes.Add(child);        

        return child;
    }

}

错误是:'Parser.Objects.TreeNode' 不包含接受 0 个参数的构造函数

请帮忙!

【问题讨论】:

    标签: c# generics constructor multiple-inheritance


    【解决方案1】:

    您需要添加对基类的构造函数的调用。

    随后,您不需要在 FHXTreeNode 的构造函数中设置属性,因为它是在基类的构造函数中处理的。您的新构造函数应如下所示:

    public FHXTreeNode(FHXTreeNode<T> parent, T data) : base(parent, data)
    {
    }
    

    【讨论】:

    • 非常感谢。这是一个很大的帮助!
    【解决方案2】:

    你需要调用基类的构造函数。如果省略:base(...) 调用,则调用基类的无参数构造函数。由于你的基类没有这样的构造函数,你会得到一个错误。

    public FHXTreeNode(FHXTreeNode<T> parent, T data)
       :base(parent, data)
    {
    }
    

    调用参数化基类构造函数也会使字段初始化过时,因为它们已经在基类中分配。

    在 C# 中,您不能继承构造函数。您在派生类中创建一个新的构造函数,该构造函数恰好与基类构造函数具有相同的签名。


    你的接口也坏了:你不能在接口中将方法声明为public abstract。接口方法总是隐式公开的,并且永远不会有实现。所以这些修饰符是多余的,而且是非法的。


    接下来你不能override 接口方法。您只能覆盖 基类 中的 virtual/abstract 方法。当您有一个与接口中的方法匹配的方法时, in 实现该接口方法。


    还有一个错误是你在接口方法上重用了类型参数:void AddChild&lt;T&gt;(T child); 是错误的。此语法用于在方法中引入类型参数。但是您想使用包含类型的类型参数。所以你应该写AddChild(T child);


    还有一些风格问题:接口名称应以I 为前缀。我会尽可能避免使用protected 字段。

    【讨论】:

    • 感谢您的输入,其实我想做的是在方法中引入类型参数,所以我应该取出接口名称中的。非常感谢您的建议。
    • 您确定要在方法中而不是在接口类型中引入类型参数吗?将这些方法通用化毫无意义。
    • 是的,因为创建这些接口是因为我意识到,例如,并非所有树都以相同的方式添加子树。如果我把它放在抽象基类中,我将不得不重载 addChild 方法,结果代码会比现在更糟糕。由于并非所有树都以相同的方式添加和搜索子树,因此我正在考虑采用一种策略模式来实现这些树操作。
    【解决方案3】:

    您必须从 FHXTreeNode 构造函数中调用基类构造函数:

    public FHXTreeNode(FHXTreeNode<T> parent, T data)
        : base(parent, data)
    {
        ParentNode = parent;
        ObjectData = data;
    }
    

    另外,按照惯例,.NET 中的接口以大写 I 开头,因此 TreeNodeOperations 应该是 ITreeNodeOperations

    【讨论】:

      【解决方案4】:

      首先,publicabstract 不是接口声明中的有效关键字。您的界面应如下所示:

      interface TreeNodeOperations<T>
      {
          //Adds child to tree node
          void AddChild(T child);
          //Performs N-Tree search
          TreeNode<T> SeachChild(T child);
      }
      

      回答你的问题,因为TreeNode 没有像这样定义无参数构造函数:

      public TreeNode() { }
      

      ...如果不调用它的基本构造函数,就无法创建 FHXTreeNode 的实例,如下所示:

      public FHXTreeNode(FHXTreeNode<T> parent, T data) : base(parent, data) { }
      

      【讨论】:

        猜你喜欢
        • 2018-12-22
        • 2020-09-11
        • 2019-01-21
        • 2017-08-09
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-11-14
        • 2021-06-24
        相关资源
        最近更新 更多