Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/json/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何在C#中使用泛型创建入侵树类?_C#_Data Structures_Intrusive Containers - Fatal编程技术网

如何在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; } } 可以添加到树中的各种对象继承自节点或容器,具体取决于它

在C#中,我有一个侵入式树结构,如下所示:

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; }
    }
}