我发现了一个问题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.所以欢迎提出建议和解释。
答案 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>();
}
//...
}
}