У меня есть класс, содержащий частный список. Я создал геттер и метод для добавления элементов в список:

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 ().

3
Ignacio 26 Фев 2016 в 15:14

4 ответа

Лучший ответ

Если вы используете как минимум .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);
    }
}
7
Daniel A. White 26 Фев 2016 в 12:16

В классе Test выставьте 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);
    }
}

Edit обновил IEnumerable до IReadOnlyList. Использование IReadOnlyList дает определенные преимущества - IEnumerable & lt; T & gt; по сравнению с IReadOnlyList & lt; T & gt;

3
Community 23 Май 2017 в 12:23

Если единственная причина для вашего геттера - добавление элементов, вам вообще не понадобится прямой доступ к списку, но вы можете обернуть вызов метода 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 не раскрывает общий список.

1
HimBromBeere 26 Фев 2016 в 12:26

Я бы вернулся как 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);
    }
}

Таким образом вы предотвратите приведение типов ... Это обернет ваш List<> классом ReadOnlyCollection.


Или вы можете вернуть его как Array, например:

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

Метод 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);
4
Jeroen van Langen 26 Фев 2016 в 13:36