简体   繁体   中英

Block the List.Add() method

I have a class that contains a private List. I have created a getter and a method to add elements to the list:

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);
    }
}

Since everytime an element is added to my list I want to do more things, I do not want that in some part of the code someone add an element directly:

Test test = new Test();

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

// Right
test.AddElements(element);

I have thought on creating a new class that implements the IList interface and overrides the Add() method, but I was wondering if there is a more simple/elegant way on "block" this Add() method.

If you are using at least .NET 4.5, return a 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);
    }
}

In Test class expose the List as IReadOnlyList<T> then you wont be allowed to use MyList.Add directly

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);
    }
}

Edit updated it IEnumerable to IReadOnlyList. There are benifits in using IReadOnlyList - IEnumerable<T> vs IReadOnlyList<T>

I would return as ReadOnlyCollection<T>

Use it like:

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);
    }
}

This way you prevent casting... It will Wrap your List<> with a ReadOnlyCollection class.


Or you could return it as an Array like:

public T[] MyList
{
    get { return myList.ToArray(); }
}

The ToArray() method will create a copy of the list


When it is Returned as an IReadOnlyList<T> . You could simply cast it back..

Test test = new Test<int>();

test.AddElements(10);

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

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

If the only reason for your getter is to add elements you won´t need to directly access the list at all, but you can wrap the call to the Add -method into your own method:

class MyClass<T> {
    private List<T> _myList ...

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

Exposing a generic list is furthermore avoided by CA1002

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM