内部类通用类型与外部类型相同

时间:2016-08-02 13:56:24

标签: c# generics

我发现了一个问题here 几乎回答了我的问题,但我仍然不能完全理解。

尝试编写Tree数据结构,我这样做了:

public class Tree<T>
{
    public TreeNode<T> root;
    ...

    public class TreeNode<T>
    {
        List<TreeNode<T>> children;
        T data;
        public T Data { get { return data; } }

        public TreeNode<T>(T data)
        {
            this.data = data;
            children = new List<TreeNode<T>>();
        }
        ...
    }
}

而且,任何与C#generics合作的人显然都知道我收到了这个编译器警告:Type parameter 'T' has the same name as the type parameter from outer type 'Tree<T>'

我的意图是创建一个内部类,它将被强制使用与外部类相同的类型,但我现在明白添加一个类型参数实际上允许内部类更灵活。但是,就我而言,我希望Tree<T>的子类能够使用TreeNode,例如,像这样:

public class IntTree : Tree<int>
{
    ...
    private static IntTree fromNode(TreeNode<int> node)
    {
        IntTree t = new IntTree();
        t.root = node;
        return t;
    }
}

(该方法允许子类递归地实现ToString()

所以我的问题是,如果我拿出参数化,就像这样:

public class Tree<T>
{
    public TreeNode root;
    ...

    public class TreeNode
    {
        List<TreeNode> children;
        T data;
        public T Data { get { return data; } }

        public TreeNode(T data)
        {
            this.data = data;
            children = new List<TreeNode>();
        }
        ...
    }
}

在创建TreeNode时,会强制生成的子类使用整数,因此永远无法打破我的意图吗?

免责声明:是的,我知道我可能在这里犯了很多错误。我还在学习C#,来自一个主要是Java和Lisp的背景,还有一点点简单的C.所以欢迎提出建议和解释。

2 个答案:

答案 0 :(得分:2)

是的,它将被强制使用相同的类型。再看一下声明:

public class Tree<T>
{
    public class TreeNode
    {
        private T Data;
    }
}

因此,当您实例化特定Data时,会确定Tree的类型:

var tree = new Tree<int>();

这样Data的类型被声明为int,并且可以没有什么不同。

请注意,没有非通用TreeNode类。只有Tree<int>.TreeNode类型:

Tree<int> intTree = new Tree<int>(); // add some nodes
Tree<int>.TreeNode intNode = intTree.Nodes[0]; // for example

Tree<string> stringTree = new Tree<int>(); // add some nodes
Tree<string>.TreeNode stringNode = stringTree.Nodes[0]; // for example

// ERROR: this won't compile as the types are incompatible
Tree<string>.TreeNode stringNode2 = intTree.Nodes[0]; 

Tree<string>.TreeNode与<{1}}不同的类型。

答案 1 :(得分:0)

外部类中声明的类型T可能已经在其所有内部声明中使用,因此您只需从内部类中删除<T>

public class Tree<T>
{
    public TreeNode root;
    //...

    public class TreeNode
    {
        List<TreeNode> children;
        T data;
        public T Data { get { return data; } }

        public TreeNode(T data)
        {
            this.data = data;
            children = new List<TreeNode>();
        }
       //...
    }
}