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

时间:2011-12-15 19:45:10

标签: c# oop

定义这样的东西有什么不妥之处:

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

5 个答案:

答案 0 :(得分:7)

不,因为答案至少需要30个字符,我会补充说这是一种常见的模式。

但是,由于您包含了oop标记,我将补充说,此模式可以为外界提供很多控制。例如,如果c是一个子项列表,那么您可以授予每个有权访问ObjectA实例的人添加,删除或替换其子项的权限。

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

修改

请注意,以下内容仍允许其他人修改您的列表:

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

缺少setter只会阻止外人替换列表对象。

答案 1 :(得分:6)

不。那是完全可以接受的。树结构就是这样做的。

答案 2 :(得分:1)

完全有效。例如,您必须执行类似的操作来构建树数据结构(父节点包含子节点列表)。

答案 3 :(得分:1)

我不得不问你的问题是关于放一个List&lt; &GT;在那里,或者如果它是关于放一个List&lt; ObjectA&gt;在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;} }


}

答案 4 :(得分:1)

没有。这是有效的。许多结构使用此图形,如模式。

如果你有一个基础集合类

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分钟内编写的内容,而且在生产中存在问题并不好,但主要的两个问题是您有一个父节点和许多子节点。将子节点添加到给定节点时,请确保它已设置其父节点。在这里,我首先检查孩子是否已经在子列表中,然后连接两者。 您可以对代码进行一些更改,并确保如果删除子项,则父项列出它已全部已连接到。我没有在那里做过。

我这样做是为了说明如何使用它。它被用在很多地方。 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; }
    }
}

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

树木和图表有很多规则,我的图表甚至是真实的图表。但我已经把这些例子放在这里,所以你可以看到它被大量使用!!如果您想更多地了解线性和其他数据结构,请参阅此serie of articles。第3部分,第4部分和第5部分他们谈论了很多关于树木和图表的内容。