禁止公共添加和删除列表<t> </t>

时间:2010-06-16 12:01:31

标签: c# list

在我的C#项目中,我有一个包含List

的类
public class MyClass
{
  public MyClass parent;
  public List<MyClass> children;
  ...
}

我想阻止类的用户将一个元素添加(和删除)到children-List,但是他仍然可以解析它的元素。我想在MyClass中处理添加和删除,提供AddChild(MyClass项)和DeleteChild(MyClass项),以确保在将项添加到子列表时,将正确设置该项的父项。

除了实现我自己的IList之外,还知道如何做到这一点吗?

提前致谢, 弗兰克

8 个答案:

答案 0 :(得分:29)

如果你给来电者List<T>,你无法控制这个;你甚至不能继承List<T>,因为添加/删除不是virtual

相反,我会将数据公开为IEnumerable<MyClass>

private readonly List<MyClass> children = new List<MyClass>();
public void AddChild(MyClass child) {...}
public void RemoveChild(MyClass child) {...}
public IEnumerable<MyClass> Children {
    get {
        foreach(var child in children) yield return child;
    }
}

yield return阻止他们只是投射它)

来电者仍然可以在foreach上使用.Children,感谢LINQ,他们也可以做其他所有有趣的事情(WhereFirst等。)< / p>

答案 1 :(得分:14)

除了实施您自己的IList<T>之外,您还可以返回ReadOnlyCollection<MyClass>

public MyClass
{
    public MyClass Parent;

    private List<MyClass> children;
    public ReadOnlyCollection<MyClass> Children
    {
        get { return children.AsReadOnly(); }
    }
}

答案 2 :(得分:6)

将列表公开为IEnumerable<MyClass>

答案 3 :(得分:3)

将列表设为私有,并创建公共方法以从类外部访问其内容。

public class MyClass
{
    public MyClass Parent { get; private set; }

    private List<MyClass> _children = new List<MyClass>();
    public IEnumerable<MyClass> Children
    {
        get
        {
            // Using an iterator so that client code can't access the underlying list
            foreach(var child in _children)
            {
                yield return child;
            }
        }
    }

    public void AddChild(MyClass child)
    {
        child.Parent = this;
        _children.Add(child);
    }

    public void RemoveChild(MyClass child)
    {
        _children.Remove(child);
        child.Parent = null;
    }
}

顺便说一句,避免声明公共字段,因为你无法控制客户端代码对它们的作用。

答案 4 :(得分:1)

using System.Collections.ObjectModel;

public class MyClass
{
    private List<MyClass> children;

    public ReadOnlyCollection<MyClass> Children
    {
        get
        {
            return new ReadOnlyCollection<MyClass>(children);
        }
    }
}

答案 5 :(得分:0)

您不需要重新实现IList,只需将List封装在类中,并提供自己的Add和Delete函数,这些函数将负责添加和设置所需的属性。

如果您想通过列表枚举,则可能必须创建自己的枚举器。

答案 6 :(得分:0)

您可以通过将列表设为私有来将列表封装在类中,并将其作为ReadOnlyCollection提供:

public class MyClass {

  public MyClass Parent { get; private set; };

  private List<MyClass> _children;

  public ReadOnlyCollection<MyClass> Children {
    get { return _children.AsReadOnly(); }
  }

  public void AddChild(MyClass item) {
    item.Parent = this;
    _children.Add(item);
  }

  public void DeleteChild(MyClass item) {
    item.Parent = null;
    _children.Remove(item);
  }

}

您可以使用私有设置器创建Parent属性,这样就无法从外部修改它,但AddChildDeleteChild方法可以更改它。 / p>

答案 7 :(得分:0)

使用List(T).AsReadOnly()

http://msdn.microsoft.com/en-us/library/e78dcd75.aspx

  

返回只读IList&lt;(Of&lt;(T&gt;)&gt;)   当前集合的包装器。

自.NET 2.0起可用。