Преобразование IEnumerable <T>в IList - PullRequest
9 голосов
/ 04 января 2010

Если метод принимает параметр типа System.Collections.IList, могу ли я законно / безопасно передать значение типа System.Collections.Generic.IEnumerable<T>?

Буду признателен за подробное объяснение того, почему это возможно и что на самом деле происходит с объектом T, когда IEnumerable<T> используется внутри метода.

Преобразован ли он в базовый тип объекта?

Используется ли он как System.Collections.IEnumerable?

Существуют ли сценарии, в которых это может вызвать проблемы (т.е. проблемы с производительностью)?

Заранее спасибо, John

Ответы [ 5 ]

27 голосов
/ 04 января 2010

Нет , Вы не можете передать IEnumerable<T> методу, который принимает IList. Интерфейс IEnumerable<T> не может быть преобразован в IList, и попытка передать переменную типа IEnumerable<T> в метод, принимающий IList, приведет к ошибке компиляции.

Чтобы выполнить эту работу, вам нужно выполнить одно из следующих действий:

  1. Вместо IEnumerable<T> сохраните ссылку на тип, который реализует как IEnumerable<T>, так и IList. List<T> хороший кандидат здесь
  2. Преобразовать экземпляр IEnumerable<T> в новый объект, который можно преобразовать в IList. Например, в 3.5+ вы можете вызвать метод расширения .ToList(), чтобы создать новый List<T> поверх перечисления.
4 голосов
/ 04 января 2010

Вам нужно будет позвонить ToList(). http://msdn.microsoft.com/en-us/library/bb342261.aspx

2 голосов
/ 04 января 2010

Нет. Вы не можете без использования метода расширения ToList(). Я думаю, что это не должно вызывать такой большой проблемы с производительностью - если у вас есть альтернатива, оцените их и сравните.

Вы также можете использовать new List<T>(myIEnumerable) - в документации сказано, что эта функция - операция O(n), но я не могу найти ничего другого о ToList(). Также помните, что List<T> также реализует IList и IList<T>.

1 голос
/ 04 января 2010

IEnumerable не разрешает индексированный доступ к коллекции, в то время как IList делает. Таким образом, IList более чем IEnumerable, и вы не сможете сойти с рук. Конечно, некоторые классы реализуют оба интерфейса (например, List <>), и они будут работать нормально.

Если вам нужно перейти от IEnumerable к IList, вы можете сначала попробовать приведение, если вам повезет, это сработает. Если нет, вам придется просмотреть коллекцию IEnumerable и создать новый IList.

Редактировать: используйте ToList () вместо того, чтобы предавать себя, как предлагали другие.

0 голосов
/ 04 января 2010

Нет, вы не можете передать его IEnumerable. IList реализует IEnumerable, поэтому, если вы передадите свой метод IList, вы можете безопасно использовать его как IEnumerable. VS не будет компилировать следующее:

private static void Test(IList<int> list){ }

Test(Enumerable.Range(0, 10));

Ошибка вернулась:

Argument '1': cannot convert from System.Collections.Generic.IEnumerable<int>' to 'System.Collections.Generic.IList<int>'
...