如何在C#中使用泛型创建入侵树类?
在C#中,我有一个侵入式树结构,如下所示:如何在C#中使用泛型创建入侵树类?,c#,data-structures,intrusive-containers,C#,Data Structures,Intrusive Containers,在C#中,我有一个侵入式树结构,如下所示: public abstract class Node { Container parent; Node nextNode; Node previousNode; public abstract class Container : Node { Node firstChild; Node lastChild; } } 可以添加到树中的各种对象继承自节点或容器,具体取决于它
public abstract class Node
{
Container parent;
Node nextNode;
Node previousNode;
public abstract class Container : Node
{
Node firstChild;
Node lastChild;
}
}
可以添加到树中的各种对象继承自节点
或容器
,具体取决于它们是否可以有子对象
通过使容器
成为一个内部类,这意味着它可以访问节点
中的私有成员来管理容器的子级列表
这一切都很好。但现在我希望使其通用化,以便在维护类型安全的同时重用它——基本上将所有树功能移动到节点上方的通用类,以及节点和容器之间的通用类。以下是我尝试做的一个粗略设计:
public abstract class GenericNode<Node, Container>
where Node : GenericNode<Node, Container>
where Container : GenericNode<Node, Container>.GenericContainer
{
Container parent;
Node nextNode;
Node previousNode;
public abstract class GenericContainer : Node
{
Node firstChild;
Node lastChild;
}
}
公共抽象类GenericNode
其中节点:GenericNode
其中容器:GenericNode.GenericContainer
{
容器母材;
节点下一节点;
节点前一节点;
公共抽象类GenericContainer:节点
{
节点第一子节点;
节点最后一个子节点;
}
}
当然,这不起作用,因为您无法使GenericContainer
从节点继承(编译器错误)。即使我放弃了内部类需求(比如,通过使用internal
并在我自己的库中小心),我仍然无法找到一个不会遇到相同问题(和错误)的设计
(我不认为我必须这样做,但我只是想说清楚:我不是在试图“修复”编译错误,也不是在寻找一个简单的树实现。这是一个容器设计问题。)
所以现在我有点不知所措。有人对如何设计这个东西有更好的想法吗
编辑:请务必看一看,这是另一种尝试,它试图使用扩展方法来避免将类“注入”到继承层次结构中的问题(但不幸的是,它没有完全起作用)。我的解决方案如下所示:
public class Tree<T> : ITree<T> where T : INode{
public T RootNode { get; private set; }
public Tree(T rootNode){
RootNode = rootNode;
}
}
public interface ITree<T> where T : INode{
T RootNode { get; }
}
public interface INode{
INode Parent { get; }
List<INode> Children { get; }
}
internal class Node : INode{
public INode Parent { get; private set; }
public List<INode> Children { get; private set; }
public Node( INode parent, List<INode> children = new List<INode>()){
Parent = parent;
Children = children;
}
}
公共类树:ITree其中T:INode{
公共T根节点{get;私有集;}
公共树(T根节点){
RootNode=RootNode;
}
}
公共接口ITree,其中T:INode{
T RootNode{get;}
}
公共接口节点{
INode父节点{get;}
列出子项{get;}
}
内部类节点:INode{
公共INode父节点{get;private set;}
公共列表子项{get;private set;}
公共节点(INode父节点,List子节点=new List()){
父母=父母;
儿童=儿童;
}
}
嗯
注意:其他验证,如ParentNode!=子节点为空;节点属于要将其添加到的同一父节点等。此示例中未实现。按照扩展方法的方法,如果在接口上定义继承约束(节点和容器之间),并用接口装饰容器类,该怎么办
{
MyNode n = new MyNode();
var c = new MyNode.MyContainer();
c.AddChild(n);
MySubNode s = new MySubNode();
c.AddChild(s);
OtherNode o = new OtherNode();
o.AddChild(o);
//compiler doesn't allow this, as you'd expect:
//c.AddChild(o);
}
public interface IContainer<TContainerType, TNodeType>
where TNodeType : GenericNode<TContainerType, TNodeType>
where TContainerType : TNodeType, IContainer<TContainerType, TNodeType>
{
}
public static class ContainerExtensions
{
public static void AddChild<TContainerType, TNodeType>(this IContainer<TContainerType, TNodeType> self, TNodeType node)
where TNodeType : GenericNode<TContainerType, TNodeType>
where TContainerType : TNodeType, IContainer<TContainerType, TNodeType>
{
GenericNode<TContainerType, TNodeType>.AddChild(self as TContainerType, node);
}
}
public class GenericNode<TContainerType, TNodeType>
where TNodeType : GenericNode<TContainerType, TNodeType>
where TContainerType : GenericNode<TContainerType, TNodeType>
{
TContainerType parent;
TNodeType nextNode;
TNodeType previousNode;
// Only used by Container
TNodeType firstChild;
TNodeType secondChild;
internal static void AddChild(TContainerType container, TNodeType node)
{
container.firstChild = node;
node.parent = container;
}
}
public class MyNode : GenericNode<MyContainer, MyNode>
{
}
public class MyContainer : MyNode, IContainer<MyContainer, MyNode>
{
}
public class MySubNode : MyNode
{
}
public class OtherNode : GenericNode<OtherNode, OtherNode>, IContainer<OtherNode, OtherNode>
{
}
{
MyNode n=新的MyNode();
var c=new MyNode.MyContainer();
c、 AddChild(n);
MySubNode s=新的MySubNode();
c、 AddChild(s);
OtherNode o=新的OtherNode();
o、 AddChild(o);
//编译器不允许这样做,正如您所料:
//c、 AddChild(o);
}
公共接口IContainer
其中TNodeType:GenericNode
其中TContainerType:TNodeType,IContainer
{
}
公共静态类ContainerExtensions
{
公共静态void AddChild(此IContainer自身,TNodeType节点)
其中TNodeType:GenericNode
其中TContainerType:TNodeType,IContainer
{
AddChild(自身作为TContainerType,节点);
}
}
公共类泛型节点
其中TNodeType:GenericNode
其中TContainerType:GenericNode
{
TContainerType父代;
TNodeType nextNode;
TNodeType-previousNode;
//仅用于集装箱
tNODE型第一胎;
tNODE型二孩;
内部静态void AddChild(TContainerType容器、TNodeType节点)
{
container.firstChild=节点;
node.parent=容器;
}
}
公共类MyNode:GenericNode
{
}
公共类MyContainer:MyNode,IContainer
{
}
公共类MySubNode:MyNode
{
}
公共类OtherNode:GenericNode、IContainer
{
}
(不要这样做-将其留在内存中,以帮助防止其他任何人意外掉落扩展;)
这有用吗
public abstract class GenericNode<Node, Container>
where Node : GenericNode<Node, Container>
where Container : GenericNode<Node, Container>.GenericContainer<Node>
{
Container parent;
Node nextNode;
Node previousNode;
public abstract class GenericContainer<Branch> where Branch: GenericNode<Node, Container>
{
private Leaf firstChild;
private Leaf secondChild;
}
}
公共抽象类GenericNode
其中节点:GenericNode
其中容器:GenericNode.GenericContainer
{
容器母材;
节点下一节点;
节点前一节点;
公共抽象类GenericContainer,其中分支:GenericNode
{
私生子;
私生子;
}
}
也在3.5中编译<代码>分支
被GenericNode
声明限制为节点。我以为我有一个可行的解决方案,但它没有完全起作用:
public abstract class GenericNode<Node, Container>
where Node : GenericNode<Node, Container>
where Container : Node
{
Container parent;
Node nextNode;
Node previousNode;
// Only used by Container
Node firstChild;
Node secondChild;
public static class ContainerHelpers
{
public static void AddChild(Container c, Node n)
{
c.firstChild = n; // not a real implementation ;)
n.parent = c;
}
}
}
// EDIT: This does not work correctly! (see example below)
public static class GenericNodeExtensionMethods
{
public static void AddChild<Node, Container>(this Container c, Node n)
where Node : GenericNode<Node, Container>
where Container : Node
{
GenericNode<Node, Container>.ContainerHelpers.AddChild(c, n);
}
}
//
// Example Usage
//
public class MyNode : GenericNode<MyNode, MyContainer>
{
}
public class MyContainer : MyNode
{
}
public class MySubNode : MyNode
{
}
public class OtherNode : GenericNode<OtherNode, OtherNode>
{
}
class Program
{
static void Main(string[] args)
{
MyNode n = new MyNode();
MyContainer c = new MyContainer();
c.AddChild(n);
MySubNode s = new MySubNode();
//
// This does not work because it tries to fill the generic in the
// extension method with <MySubNode, MyContainer>, which does not
// fulfil the constraint "where Container : Node".
//
//c.AddChild(s);
OtherNode o = new OtherNode();
o.AddChild(o);
}
}
公共抽象类GenericNode
其中节点:GenericNode
where容器:节点
{
容器母材;
节点下一节点;
节点前一节点;
//仅用于集装箱
节点第一子节点;
节点二级子节点;
公共静态类容器帮助器
{
公共静态void AddChild(容器c,节点n)
{
c、 firstChild=n;//不是真正的实现;)
n、 父母=c;
}
}
}
//编辑:这不能正常工作!(见下面的示例)
公共静态类GenericNodeExtensionMethods
{
公共静态void AddChild(此容器c,节点n)
其中节点:GenericNode
where容器:节点
{
GenericNode.ContainerHelpers.AddChild(c,n);
}
}
//
//示例用法
//
公共类MyNode:GenericNode
{
}
公共类MyContainer:MyNode
{
}
公共类MySubNode:MyNode
{
}
公共类OtherNode:GenericNode
{
}
班级计划
{
静态void Main(字符串[]参数)
{
MyNode n=新的MyNode();
MyContainer c=新的MyContainer();
c、 AddChild(n);
public interface ITagged<T>
{
T Tag { get; set; }
}
public sealed class Tree<T>
{
//All Tree operations are performed here (add nodes, remove nodes, possibly move nodes, etc.)
//Nodes are only exposed as 'ITagged<T>', such as:
public ITagged<T> Root { get; private set; }
public IEnumerable<ITagged<T>> GetChildren(ITagged<T> item)
{
//Cast to Container and enumerate...
}
//Several other tree operations...
private class Node : ITagged<T>
{
Container parent;
Node nextNode;
Node previousNode;
public T Tag { get; set; }
}
private class Container : Node
{
Node firstChild;
Node lastChild;
}
}
public abstract class GenericNode<TNode, TContainer>
where TNode : GenericNode<TNode, TContainer>
where TContainer : GenericNode<TNode, TContainer>.GenericContainer
{
public TContainer Parent { get; set; }
public TNode Next { get; set; }
public TNode Previous { get; set; }
public abstract class GenericContainer : GenericNode<TNode, TContainer>
{
public TNode FirstChild { get; set; }
public TNode LastChild { get; set; }
}
}