阻止List.Add()方法

3

我有一个包含私有List的类。我已经创建了一个getter方法和一个用于向列表添加元素的方法:

public class Test{

    private List<T> myList;
    public List<T> MyList
    {
        get { return myList; }
    }

    public Test()
    {
         myList = new List<T>();
    }

    public void AddElements(T element)
    {
         // Do dome stuff, subscribe to an event of T
         myList.Add(element);
    }
}

由于每次添加元素时我都想做更多的事情,我不希望在代码的某个部分中直接添加元素:

Test test = new Test();

// Wrong
test.MyList.Add(element);

// Right
test.AddElements(element);

我考虑创建一个新的类来实现IList接口并覆盖Add()方法,但是我想知道是否有更简单/更优雅的方法来“阻止”这个Add()方法。


1
如果您不希望其他人能够修改列表,请不要公开 List。您可以公开 ReadOnlyCollection,这样就没有人可以添加(除非他们使用反射)。 - Sinatr
4个回答

7
如果您正在使用至少.NET 4.5,返回一个 IReadOnlyList<T>
public class Test{

    private List<T> myList;
    public IReadOnlyList<T> MyList
    {
        get { return myList; }
    }

    public Test()
    {
         myList = new List<T>();
    }

    public void AddElements(T element)
    {
         // Do dome stuff, subscribe to an event of T
         myList.Add(element);
    }
}

@JeroenvanLangen 当然可以,但总有一种方法可以获取数据。 - Daniel A. White
我认为这个程序足够好用,而且不会产生副本。就像你所说的,“总有一种方法可以获取数据”;-) - Jeroen van Langen
也许是我自己的问题,但是IReadOnlyList似乎不能保护类型转换,并且似乎可以使用类型转换添加元素。 - Vonkel.

5

我会返回ReadOnlyCollection<T>

使用方法如下:

public class Test<T> 
{

    private List<T> myList;
    public ReadOnlyCollection<T> MyList
    {
        get { return myList.AsReadOnly(); }
    }

    public Test()
    {
        myList = new List<T>();
    }

    public void AddElements(T element)
    {
        // Do dome stuff, subscribe to an event of T
        myList.Add(element);
    }
}

这样可以避免强制类型转换...它将用一个ReadOnlyCollection类来包装你的。
或者你可以将它作为一个数组返回,如下所示:
public T[] MyList
{
    get { return myList.ToArray(); }
}
< p > ToArray() 方法将创建列表的副本


当作为 IReadOnlyList<T> 返回时。您可以简单地将其强制转换回来。

Test test = new Test<int>();

test.AddElements(10);

((List<int>)test.MyList).Add(20);

foreach(var i in test.MyList)
    Console.WriteLine(i);

3
在测试类中,将List公开为IReadOnlyList<T>,那么您将无法直接使用MyList.Add。
public class Test{

    private List<T> myList;
    public IReadOnlyList<T> MyList
    {
        get { return myList; }
    }

    public Test()
    {
         myList = new List<T>();
    }

    public void AddElements(T element)
    {
         // Do dome stuff, subscribe to an event of T
         myList.Add(element);
    }
}

编辑将其更新为IReadOnlyList。使用IReadOnlyList有一些好处 - IEnumerable<T> vs IReadOnlyList<T>


1
如果你的getter的唯一目的是添加元素,那么你根本不需要直接访问列表,而是可以将对Add方法的调用包装到自己的方法中:
class MyClass<T> {
    private List<T> _myList ...

    public void AddElements(T element)
    {
         // Do dome stuff, subscribe to an event of T
         _myList.Add(element);
    }
}

通过CA1002避免了暴露通用列表。


很不幸,我需要从外面使用列表元素,因此我需要访问它... - Ignacio

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接