Список <T>. Вставка против стека <T>.Push - PullRequest
1 голос
/ 06 июля 2011

Я возвращаю IList<T> из метода.

В вызывающем классе я хочу вставить значение в начале списка / стека.

Вставка значения в List<T> выполняется медленнее, чем вставка значения в Stack<T>. Но чтобы использовать стек, мне нужно его распаковать.

Итак, вопрос в том, какой из них лучше: распаковать или использовать Insert в List<T>? Какой из них дороже?

class MyClass 
{
}

IList<MyClass> Method1()
{
}

class MainClass
{
   List<MyClass> list = (List<MyClass>)Method1();
   list.insert(0,new MyClass{...}); //insert at the start. 

   Stack<MyClass> stack = (Stack<MyClass>)Method1();
   stack.Push(new MyClass{...}); //insert at the start
}

Ответы [ 2 ]

3 голосов
/ 06 июля 2011

Вы не распаковываете здесь ни в одной из версий (хотя первая не скомпилируется ... а вторая всегда будет не работать во время выполнения) -

Однако, в любом случае, если вы выполните преобразование, будет работать только в том случае, если фактическая базовая реализация этого класса .

Если ваш метод возвращает IList<T>, я настоятельно рекомендую придерживаться IList<T> членов. Преобразование результатов в List<T> или Stack<T> (т. Е. Независимо от того, какой внутренней реализацией является, что не является Stack<T>, поскольку она не реализует IList<T>) очень опасно.

Основная причина возврата IList<T> заключается в том, чтобы преднамеренно позволить вам позже изменить внутреннюю реализацию. Method1, внутренне, может позже измениться с List<T> на какой-то другой IList<T>, что приведет к неожиданному сбою вашего кода.

При этом, если вы знаете, что внутренняя реализация может быть определенного типа, вы можете проверить это, но я бы не стал слепо читать.

1 голос
/ 08 июня 2014

Вставка значения в List<T> выполняется медленнее, чем нажатие значения в Stack<T>.

Да , по причинечто вставка в список - это операция, отличная от вставки в стек.Когда вы вставляете новый элемент в середину списка, весь последующий массив должен быть смещен на единицу.Это операция O (n).Перемещение в стек просто добавляет значение в конец внутреннего массива.Это дешево - O (1).Сопоставимая операция - List<T>.Add

Но я думаю, что здесь есть недоразумение относительно того, когда и когда использовать какой.Нет разницы между List<T> и Stack<T> в отношении реализации или производительности для одной и той же операции.Разница лишь в особенностях каждой коллекции.Вы можете имитировать всплывающее окно с Stack<T> в List<T> путем (добавления в конец списка и путем) удаления с конца: list.RemoveAt(list.Count - 1).Здесь важно то, как вы хотите его использовать.Если вы собираетесь использовать List<T> в качестве Stack<T>, откажитесь от первого и всегда используйте второе.Это проясняет ваши намерения.Таким образом, в будущем вы менее подвержены ошибкам.

Но для использования стека мне нужно его распаковать.

Здесь нет распаковки.Распаковка - это когда вы преобразуете из ссылочного типа (object, IList<T>) в тип значения (например, структуры, перечисления).Stack<T> не тип значения, следовательно, нет распаковки.Это просто справочное преобразование, сохраняющее идентичность.Это так дешево, как только может.

Итак, вопрос в том, какой из них лучше, распаковать или использовать Insert в List<T>?Какой из них дороже?

  • Ваш второй код не работает.Stack<T> не IList<T>.Таким образом, у вас есть только один выбор.

  • Insert определенно дороже, но это само по себе не означает, что вы должны использовать Stack<T>.Stack<T> не дает вам произвольный доступ через индексы, удаление из середины и т. Д. Но если вам нужен только Stack<T>, придерживайтесь его.List<T> - это слишком общая цель, с которой вы можете делать много вещей.

Итог: вы либо возвращаете Stack<T> и используете его (лучшую производительность), либо возвращаете IList<T> и использовать его (больше возможностей).В конце концов, решите, основываясь на использовании в первую очередь.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...