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

Aag*_*nor 14 c# list

在我的C#-project中,我有一个包含List的类

public class MyClass
{
  public MyClass parent;
  public List<MyClass> children;
  ...
}
Run Code Online (Sandbox Code Playgroud)

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

除了实现我自己的IList之外,还有任何想法吗?

先谢谢你,弗兰克

Mar*_*ell 30

如果你给来电者打电话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;
    }
}
Run Code Online (Sandbox Code Playgroud)

(yield return防止他们只是施放它)

调用者仍然可以使用foreach.Children,并感谢LINQ可以做所有的其他有趣的事情太(Where,First,等).

  • @spoulson - 不; 实现为"返回源"(在反射器中查看),所以我仍然可以将它转换回`List <T>`并调用`Add`.要演示,请尝试:`var list = new List <string>(); ((IList的)list.AsEnumerable())添加( "ABC"); Console.WriteLine(list.Count);` (5认同)
  • 您也可以使用`.AsEnumerable()`扩展方法而不是`foreach` /`yield`循环.http://msdn.microsoft.com/en-us/library/bb335435.aspx (3认同)
  • 最好将列表直接返回为"IEnumerable <MyClass>",因为这样LINQ可以有效地使用它.例如,用户可以使用具有O(1)性能的`.Count()`或`.ElementAt()`.他们可以通过投射来改变您的列表这一事实通常并不重要,因为如果您完全信任,他们可以通过Reflection轻松访问您的私人字段.公共合同的意图很明确:我不希望你改变这个枚举的集合,我不保证如果你尝试会发生什么. (2认同)
  • @Ozan - 不,通过`yield return`实现的IEnumerables是通过状态机懒洋洋地执行的.foreach ... yield return方法将产生与底层列表的迭代器面对并发修改时相同的结果.在没有主动枚举的情况下修改列表是可以的; 应该避免修改它(即你处于foreach循环中). (2认同)

ba_*_*end 14

除了实现你自己,IList<T>你可以返回一个ReadOnlyCollection<MyClass>.

public MyClass
{
    public MyClass Parent;

    private List<MyClass> children;
    public ReadOnlyCollection<MyClass> Children
    {
        get { return children.AsReadOnly(); }
    }
}
Run Code Online (Sandbox Code Playgroud)


UpT*_*eek 6

将列表公开为 IEnumerable<MyClass>