包含相同对象类型的列表的对象

本文关键字:对象 列表 类型 包含相 | 更新日期: 2023-09-27 18:18:04

这样定义有什么不对吗:

     class ObjectA
      {
         property a;
         property b;
         List <ObjectA> c;
         ...
      }

包含相同对象类型的列表的对象

不,因为答案至少需要30个字符,所以我将添加这是一个常见的模式。

由于您包含了oop标记,因此我将补充说,该模式为外部世界提供了大量控制。例如,如果c是一个子节点列表,那么您将赋予每个能够访问ObjectA实例的人添加、删除或替换其子节点的能力。

更严格的方法是使用某种只读类型(可能实现IList<ObjectA>)来公开子节点。

编辑

请注意,以下命令仍然允许其他人修改您的列表:

 class ObjectA 
  { 
     property a; 
     property b; 
     List <ObjectA> c; 
     ... 
     public List<ObjectA> Children { get { return c; } }
  } 

没有setter只会阻止外部的替换列表对象。

没有。这完全可以接受。

完全有效。例如,要构建一个树形数据结构(父节点包含一个子节点列表),您必须这样做。

我不得不问你的问题是否关于放置列表<>在那里,或者如果它是关于放一个列表内部的ObjectA。两个问题的答案都是肯定的!

要记住的是,默认情况下,访问是私有的。如果你想让其他类使用这个列表,那么你需要在你的类中添加一些东西…
class ObjectA
{
   property a;
   property b;
   List <ObjectA> c;       
   // allow access, but not assignment 
   // you can still modify the list from outside, you just cant 
   // assign a new list from outside the class
   public List<ObjectA> somePropertyName{ get { return this.c;}}
   // same as above, only allow derived child classes to set the list
   public List<ObjectA> somePropertyName{ get { return this.c;} 
                                          protected set { this.c = value;} }
   // allow all access
   public List<ObjectA> somePropertyName{ get { return this.c;} 
                                          set { this.c = value;} }

}

No。这是有效的。许多结构使用这种类似图形的模式。

如果你有一个基集合类

namespace MiniGraphLibrary
{
    public class GraphCollection
    {
        public Node Root { set; get; }
        public Node FindChild(Node root)
        {
            throw new NotImplementedException();
        }
        public Node InsertNode(Node root, Node nodeToBeInserted)
        {
            throw new NotImplementedException();
        }
    }
}

然后你可以让节点像这样运行:

namespace MiniGraphLibrary
{
    public class Node
    {
        private string _info;
        private List<Node> _children = new List<Node>();
        public Node(Node parent, string info)
        {     
            this._info = info;
            this.Parent = parent;
        }
        public Node Parent { get; set; }
        public void AddChild(Node node)
        {
            if (!this.DoesNodeContainChild(node))
            {
                node.Parent = this;
                _children.Add(node);
            }
        }
        public bool DoesNodeContainChild(Node child)
        {
            return _children.Contains(child);
        }
    }
}

请注意,这是我在2分钟内写的东西,它在生产中可能不太好,但2个主要的事情是您有一个父节点和许多子节点。向给定节点添加子节点时,要确保它具有父节点集。在这里,我首先检查子节点是否已经存在于子节点列表中,然后再连接两个子节点。您可以对代码进行一些更改,并确保如果子节点被删除,则它已经连接到父节点列表。我没有在这里做这个。

我做这个是为了说明如何使用它。它在很多地方都被使用。MSSQL中的Fx聚类索引使用某种树状表示法。但我不是这方面的专家,所以如果我说错了请纠正我。

我没有在GraphCollection类中实现这两个类。这个例子的缺点是如果你要实现Find方法,你必须遍历整个图。您可以创建一个只有两个子节点的二叉树:

namespace MiniTreeLibrary
{
    public class SimpleNode
    {
        private string _info;
        private SimpleNode _left;
        private SimpleNode _right;
        private SimpleNode _parent;
        public SimpleNode(Node parent, string info)
        {     
            this._info = info;
            this.Parent = parent;
        }
        public Node Parent { get; private set; }
    }
}

我省略了右和左的插入。现在有了这个二叉树,你可以做一些非常快的搜索,如果你想的话!!但那是另一个讨论。

当涉及到树和图时,有很多规则,我的图甚至是一个真正的图。但是我把这些例子放在这里,所以你可以看到它被使用得很多!!如果您想深入了解线性和其他数据结构,请参阅本系列文章。