Как зайти в Даркнет?!
25th January, 01:11
6
0
Как в tkinter из поля ввода Entry получить значение в одну переменную и обновить строку кнопкой, затем получить ещё одно введённое значение и затем сложить их. Ниже пример кода
21st July, 19:00
895
0
Программа, которая создает фейковые сервера в поиске игровых серверов CS 1.6 Steam
21st March, 17:43
948
0
Очень долго работает Update запрос Oracle
27th January, 09:58
914
0
не могу запустить сервер на tomcat HTTP Status 404 – Not Found
21st January, 18:02
906
0
Где можно найти фрилансера для выполнения поступающих задач, на постоянной основе?
2nd December, 09:48
938
0
Разработка мобильной кроссплатформенной военной игры
16th July, 17:57
1724
0
период по дням
25th October, 10:44
3955
0
Пишу скрипты для BAS только на запросах
16th September, 02:42
3720
0
Некорректный скрипт для закрытия блока
14th April, 18:33
4613
0
прокидывать exception в блоках try-catch JAVA
11th March, 21:11
4381
0
Помогите пожалуйста решить задачи
24th November, 23:53
6086
0
Не понимаю почему не открывается детальное описание продукта
11th November, 11:51
4351
0
Нужно решить задачу по программированию на массивы
27th October, 18:01
4396
0
Метода Крамера С++
23rd October, 11:55
4309
0
помогите решить задачу на C++
22nd October, 17:31
4002
0
Помогите решить задачу на python с codeforces
22nd October, 11:11
4492
0
Python с нуля: полное руководство для начинающих
18th June, 13:58
2599
0
Когда использовать IList и когда использовать список
Я знаю, что IList-это интерфейс, а List-конкретный тип, но я все еще не знаю, когда использовать каждый из них. То, что я делаю сейчас, если мне не нужны методы Sort или FindAll, я использую интерфейс. Разве я не прав? Есть ли лучший способ решить, когда использовать интерфейс или конкретный тип?
Есть два правила, которым я следую:
- Примите самый простой тип, который будет работать
- Верните самый богатый тип, который потребуется вашему пользователю
Таким образом, при написании функции или метода, который принимает коллекцию, напишите его не для того, чтобы принять список, но IList<T>, ICollection<T>, или IEnumerable<T>. универсальные интерфейсы все равно будут работать даже для гетерогенных списков, потому что System.Object тоже может быть T. Это избавит вас от головной боли, Если вы решите использовать стек или другую структуру данных в дальнейшем. Если все, что вам нужно сделать в функции, это foreach через нее, то IEnumerable<T>-это действительно все, что вы должны просить.
С другой стороны, возвращая объект из функции, вы хотите предоставить пользователю самый богатый набор возможных операций без необходимости их разбрасывать. Так что в этом случае, если это List<T> внутренне, верните копию как List<T>.
Рекомендации корпорации Майкрософт, проверенные FxCop, препятствуют использованию List<T> в общественных местах APIs-предпочитают IList<T>.
Кстати, теперь я почти всегда объявляю одномерные массивы как IList<T>,, что означает, что я могу последовательно использовать свойство IList<T>.Count, а не Array.Length. Например:
public interface IMyApi
{
IList<int> GetReadOnlyValues();
}
public class MyApiImplementation : IMyApi
{
public IList<int> GetReadOnlyValues()
{
List<int> myList = new List<int>();
... populate list
return myList.AsReadOnly();
}
}
public class MyMockApiImplementationForUnitTests : IMyApi
{
public IList<int> GetReadOnlyValues()
{
IList<int> testValues = new int[] { 1, 2, 3 };
return testValues;
}
}
Есть одна важная вещь, которую люди, кажется, всегда упускают из виду:
Вы можете передать простой массив чему-то, что принимает параметр IList<T> , а затем вызвать IList.Add() и получить исключение среды выполнения:
Unhandled Exception: System.NotSupportedException: Collection was of a fixed size.
Например, рассмотрим следующий код:
private void test(IList<int> list)
{
list.Add(1);
}
Если вы вызовете это следующим образом, вы получите исключение среды выполнения:
int[] array = new int[0];
test(array);
Это происходит потому, что использование простых массивов с IList<T> нарушает принцип подстановки Лисков.
По этой причине, если вы вызываете IList<T>.Add() , вы можете рассмотреть возможность использования List<T> вместо IList<T> .
Я бы согласился с Советом ли взять параметры, но не возвращаться.
Если вы зададите свои методы для возврата интерфейса, это означает, что вы можете изменить точную реализацию позже, даже не зная об этом потребляющем методе. Я думал, что мне никогда не нужно будет переходить с List<T>, но позже пришлось изменить его, чтобы использовать пользовательскую библиотеку списков для дополнительной функциональности, которую она предоставляет. Поскольку я вернул только IList<T>, никому из тех, кто пользовался библиотекой, не пришлось менять свой код.
Конечно, это должно относиться только к методам, которые являются внешне видимыми (т. е. открытые методы). Я лично использую интерфейсы даже во внутреннем коде,но поскольку вы можете изменить весь код самостоятельно, если вы вносите критические изменения, это не обязательно.
IEnumerable вы должны попытаться использовать наименее конкретный тип, который подходит для вашей цели. IEnumerable менее специфичен, чем IList Вы используете IEnumerable, когда хотите выполнить циклический перебор элементов в коллекции
IList IList реализует IEnumerable Вы должны использовать IList, когда вам нужен доступ по индексу к вашей коллекции, добавлять и удалять элементы и т. д..
Список список реализует IList
Всегда лучше использовать самый низкий базовый тип. Это дает разработчику вашего интерфейса или потребителю вашего метода возможность использовать все, что им нравится за кулисами.
Для коллекций Вы должны стремиться использовать IEnumerable, где это возможно. Это дает наибольшую гибкость, но не всегда подходит.
Если вы работаете в рамках одного метода (или даже в одном классе или assembly в некоторых случаях), и никто снаружи не будет видеть, что вы делаете, используйте полноту списка. Но если вы взаимодействуете с внешним кодом, например, возвращая список из метода, то вам нужно только объявить интерфейс, не обязательно привязывая себя к конкретной реализации, особенно если у вас нет контроля над тем, кто компилирует ваш код после этого. Если вы начали с конкретного типа и решили сменить его на другой, даже если он использует тот же интерфейс, вы нарушите чей-то код, если не начнете с интерфейса или абстрактного базового типа.
Я не думаю, что есть жесткие и быстрые правила для этого типа вещей, но я обычно иду по принципу использования самого легкого возможного способа до тех пор, пока это абсолютно необходимо.
Например, допустим, у вас есть класс Person и класс Group . Экземпляр Group имеет много людей, поэтому список здесь будет иметь смысл. Когда я объявляю объект списка в Group , я буду использовать IList<Person> и создавать его экземпляр как List .
public class Group {
private IList<Person> people;
public Group() {
this.people = new List<Person>();
}
}
И, если вам даже не нужно все в IList , вы всегда можете использовать IEnumerable тоже. С современными компиляторами и процессорами, я не думаю, что есть действительно какая-то разница в скорости, так что это больше просто вопрос стиля.
Чаще всего вы лучше всего используете наиболее общий используемый тип, в данном случае интерфейс IList или даже лучше интерфейс IEnumerable, так что вы можете легко переключить реализацию в более позднее время.
Однако в .NET 2.0 есть досадная вещь-IList не имеет метода Sort() . Вместо этого вы можете использовать прилагаемый адаптер:
ArrayList.Adapter(list).Sort()
AList объект позволяет создавать список, добавлять в него вещи, удалять его, обновлять его, индексировать в него и т.д. Список используется всякий раз, когда вы просто хотите общий список, где вы указываете тип объекта в нем, и это все.
IList с другой стороны-это интерфейс. В принципе, если вы хотите создать свой собственный тип списка, скажем, класс списка с именем BookList, то вы можете использовать интерфейс, чтобы дать вам основные методы и структуру для вашего нового класса. IList-это когда вы хотите создать свой собственный, специальный подкласс, который реализует List.
Есть еще одно отличие: IList является интерфейсом и не может быть создан экземпляр. List - это класс,и его можно создать. Это значит::
IList<string> MyList = new IList<string>();
List<string> MyList = new List<string>
В ситуациях, с которыми я обычно сталкиваюсь, я редко использую IList напрямую.
Обычно я просто использую его в качестве аргумента к методу
void ProcessArrayData(IList almostAnyTypeOfArray)
{
// Do some stuff with the IList array
}
Это позволит мне выполнять универсальную обработку практически любого массива в фреймворке .NET, если только он не использует IEnumerable, а не IList, что иногда случается.
Это действительно сводится к тому, какая функциональность вам нужна. Я бы предложил использовать класс List в большинстве случаев. IList лучше всего подходит для создания пользовательского массива, который может содержать некоторые очень специфические правила, которые вы хотели бы инкапсулировать в коллекцию, чтобы не повторяться, но все же хотите, чтобы .NET распознал его как список.
Вы должны использовать интерфейс только в том случае, если он вам нужен, например, если ваш список приведен к реализации IList, отличной от списка. Это верно, например, когда вы используете NHibernate, который приводит ILists в объект NHibernate bag при извлечении данных.
Если List-это единственная реализация, которую вы когда-либо будете использовать для определенной коллекции, не стесняйтесь объявлять ее конкретной реализацией List.