在C#中是否可以定义一个引用自身的泛型类型?
例如,我想定义一个Dictionary<>,它将其类型作为TValue(用于层次结构)。
Dictionary<string, Dictionary<string, Dictionary<string, [...]>>>
在C#中是否可以定义一个引用自身的泛型类型?
例如,我想定义一个Dictionary<>,它将其类型作为TValue(用于层次结构)。
Dictionary<string, Dictionary<string, Dictionary<string, [...]>>>
尝试:
class StringToDictionary : Dictionary<string, StringToDictionary> { }
然后你可以写:
var stuff = new StringToDictionary
{
{ "Fruit", new StringToDictionary
{
{ "Apple", null },
{ "Banana", null },
{ "Lemon", new StringToDictionary { { "Sharp", null } } }
}
},
};
递归的一般原则是:找到一种方式,给递归模式取一个名字,这样它就可以通过名称引用自身。
using
定义别名,但不幸的是,你不能在开放式泛型类型中使用 using
,这也意味着我们无法定义开放式泛型类型的 Curried 或部分应用。这是 C# 的一个令人烦恼的限制。 - Dai另一个例子是通用树
public class Tree<TDerived> where TDerived : Tree<TDerived>
{
public TDerived Parent { get; private set; }
public List<TDerived> Children { get; private set; }
public Tree(TDerived parent)
{
this.Parent = parent;
this.Children = new List<TDerived>();
if(parent!=null) { parent.Children.Add(this); }
}
public bool IsRoot { get { return Parent == null; } }
public bool IsLeaf { get { return Children.Count==0; } }
}
现在开始使用它
public class CoordSys : Tree<CoordSys>
{
CoordSys() : base(null) { }
CoordSys(CoordSys parent) : base(parent) { }
public double LocalPosition { get; set; }
public double GlobalPosition { get { return IsRoot?LocalPosition:Parent.GlobalPosition+LocalPosition; } }
public static CoordSys NewRootCoordinate() { return new CoordSys(); }
public CoordSys NewChildCoordinate(double localPos)
{
return new CoordSys(this) { LocalPosition = localPos };
}
}
static void Main()
{
// Make a coordinate tree:
//
// +--[C:50]
// [A:0]---[B:100]--+
// +--[D:80]
//
var A=CoordSys.NewRootCoordinate();
var B=A.NewChildCoordinate(100);
var C=B.NewChildCoordinate(50);
var D=B.NewChildCoordinate(80);
Debug.WriteLine(C.GlobalPosition); // 100+50 = 150
Debug.WriteLine(D.GlobalPosition); // 100+80 = 180
}
请注意,您不能直接实例化Tree<TDerived>
。 它必须是树中节点类的基类。考虑使用class Node:Tree<Node> { }
。
TDerived Parent { get; }
,可以自动满足而无需在派生类中显式声明CoordSys Parent { get; }
。重要的是所有未出现的代码。 - John AlexiouCoordSys
是一个Tree<CoordSys>
。类型是数据结构和数据本身,而不是有一个Node<T>
作为数据结构和T
作为数据。使用递归泛型类型简化了很多代码,并且泛型约束赋予了T
比object
更强大的能力,使其自我感知其方法和属性。 - John AlexiouCoordSys : Tree<CoordSys>
声明及其功能——这是一种相当不错的方式,可以确保某种类型的“自我”引用,因此对于包含自己类型对象引用/指针的各种链接列表/结构的声明非常有用。而泛型的Tree<CoordSys>
则声明了这些引用应该是什么。但如果在你的代码中删除了Tree<TDerived>
声明中的where TDerived : Tree<TDerived>
,会出现什么问题?没有它的话,一切都能完美地工作吗? - John Ppublic class Tree<TDerived> where TDerived : Tree<TDerived>
中的where
可能很有用,例如,如果我们想要声明一些其他的SpecialList<Tderived> : Tree<TDerived>
类 - Tree<TDerived>
类中的where
将确保我们只能使用继承自Tree<TDerived>
的类型TDerived
来使用SpecialList
。但在您的示例中,这种情况并没有发生,也没有任何地方实例化Tree<TDerived>
,因此我不明白where
如何改变任何功能或确保任何行为。 - John P