C # / .NET эквивалент для коллекций Java. <T>emptyList ()? - PullRequest
33 голосов
/ 09 октября 2010

Какой стандартный способ получить типизированный, только для чтения пустой список в C # или он есть?

ETA: Для тех, кто спрашивает «почему?»: У меня есть виртуальный методэто возвращает IList (или, скорее, пост-ответы, IEnumerable), и реализация по умолчанию пуста.Все, что возвращает список, должно быть доступно только для чтения, потому что запись в него будет ошибкой, и если кто-то попытается это сделать, я хочу немедленно прекратить работу и загореться, а не ждать, пока ошибка обнаружится каким-то тонким способом позже.

Ответы [ 8 ]

24 голосов
/ 24 июля 2011

Лично я думаю, что это лучше, чем любой другой ответ:

static readonly IList<T> EmptyList = new T[0];
  • Массив реализует IList<T>.
  • Вы не можете добавить в массив.
  • Нельзя назначить элемент в пустом массиве (поскольку равно нет).
  • Это, на мой взгляд, намного проще, чем new List<T>().AsReadOnly().
  • Вы все еще можете вернуть IList<T> (если хотите).

Кстати, это то, что Enumerable.Empty<T>() фактически использует под капотом, если я правильно помню. Так что теоретически вы могли бы даже сделать (IList<T>)Enumerable.Empty<T>() (хотя я не вижу веской причины для этого).

22 голосов
/ 09 октября 2010

Вы можете просто создать список:

List<MyType> list = new List<MyType>();

Если вы хотите пустое значение IEnumerable<T>, используйте Enumerable.Empty<T>():

IEnumerable<MyType> collection = Enumerable.Empty<MyType>();

Если вы действительно хотите список только для чтения , вы можете сделать:

IList<MyType> readonlyList = (new List<MyType>()).AsReadOnly();

Возвращает ReadOnlyCollection<T>, который реализует IList<T>.

8 голосов
/ 06 октября 2016

Начиная с .net 4.6 вы также можете использовать:

IList<T> emptyList = Array.Empty<T>();

Это создаст новый экземпляр только один раз для каждого другого типа, который вы указали как T.

7 голосов
/ 09 октября 2010
IList<T> list = new List<T>().AsReadOnly();

Или, если хотите, IEnumerable<>:

IEnumerable<T> sequence = Enumerable.Empty<T>();
4 голосов
/ 09 октября 2010

Если вы хотите список, содержимое которого не может быть изменено, вы можете сделать:

ReadOnlyCollection<Foo> foos = new List<Foo>().AsReadOnly();
2 голосов
/ 19 мая 2012

Чтобы раскрыть ответ Дана Тао , следующую реализацию можно использовать так же, как Enumerable.Empty<T>(), указав вместо нее List.Empty<T>().

public static class List
{
    public static IList<T> Empty<T>()
    {
        // Note that the static type is only instantiated when
        // it is needed, and only then is the T[0] object created, once.
        return EmptyArray<T>.Instance;
    }

    private sealed class EmptyArray<T>
    {
        public static readonly T[] Instance = new T[0];
    }
}

Редактировать: я изменяю приведенный выше код, чтобы отразить результаты дискуссии с Дэном Тао о ленивой или нетерпеливой инициализации поля Instance.

2 голосов
/ 09 октября 2010

Создайте экземпляр System.Collections.ObjectModel.ReadOnlyCollection из вашего списка.

List<int> items = new List<int>();
ReadOnlyCollection<int> readOnlyItems = new ReadOnlyCollection<int>(items);
0 голосов
/ 09 октября 2010

А как же:

readonly List<T> mylist = new List<T>();

Не уверен, почему вы хотите, чтобы он только для чтения; это не имеет особого смысла в большинстве сценариев, о которых я могу думать.

...