Почему Enumerable.Except может использоваться для строкового массива в C #? - PullRequest
3 голосов
/ 20 февраля 2011

Пример

Вот пример кода, который я нашел в блоге Pete on Software :

var listThree = new string[] { "Pete", "On", "Software" };  
var listFour = new string[] { "Joel", "On", "Software" };  
stringExcept = listThree.Except(listFour);

Код компилируется и запускается. Пока все хорошо.

Вопрос

Однако я не понимаю, почему это работает.

Итак, кто-нибудь может объяснить, почему я могу использовать Enumerable.Except в строковом массиве?

Возможно, мне будет понятно, если кто-то сможет объяснить, как читать подпись Enumerable.Except, и привести пример кода:

public static IEnumerable<TSource> Except<TSource>(
    this IEnumerable<TSource> first,
    IEnumerable<TSource> second
)

Что я знаю

Я знаю понятия обобщений и методов расширения. Но, очевидно, недостаточно хорош, чтобы понять пример кода выше. Я также уже использовал некоторые базовые запросы Linq.

Ответы [ 5 ]

4 голосов
/ 20 февраля 2011

Except - это метод расширения, который расширяет любой тип, реализующий IEnumerable<T>.Это включает в себя тип System.Array , который реализует IEnumerable<T>.

Примечание на связанной странице объясняет, почему в документах не показано System.Array реализации IEnumerable<T>

. В .NET Framework версии 2.0 класс Array реализует System.Collections.Generic.IList<T>, System.Collections.Generic.ICollection<T> и System.Collections.Generic.IEnumerable<T> универсальные интерфейсы.Реализации предоставляются массивам во время выполнения и, следовательно, не видны инструментам сборки документации.В результате универсальные интерфейсы не появляются в синтаксисе объявления для класса Array, и нет никаких справочных разделов для членов интерфейса, которые доступны только путем приведения массива к универсальному типу интерфейса (явные реализации интерфейса).Главное, что нужно знать при приведении массива к одному из этих интерфейсов, - это то, что члены, которые добавляют, вставляют или удаляют элементы, выбрасывают NotSupportedException.

2 голосов
/ 20 февраля 2011

Массив T (или, скажем, T[]) также является IEnumerable<T>.В вашем вопросе T равно System.StringEnumerable.Except - это метод расширения для IEnumerable<T>, поэтому он также работает для string[]stringExcept = listThree.Except(listFour); равно

stringExcept = Enumerable.Except(listThree, listFour).
2 голосов
/ 20 февраля 2011

Это просто говорит о том, что если у вас есть IEnumerable данного типа TSource, в данном случае string, вы можете за исключением этого с другим IEnumerable того же типа и получить третий IEnumerable того жевведите обратно.Ключевым моментом является то, что два IEnumerable входа должны быть одинаковыми (и, очевидно, результат будет одного типа).

1 голос
/ 20 февраля 2011

Компилятор будет сопоставлять аргумент TSource со строкой, поскольку строковый массив реализует интерфейс IEnumerable<string> и, таким образом, соответствует первому аргументу метода расширения. Таким образом, ответ состоит из двух вещей:

  • string[] реализует IEnumerable<string>
  • Компилятор достаточно умен, чтобы вывести общие аргументы
0 голосов
/ 20 февраля 2011

Метод Except возвращает элементы первого перечислимого, которые также не отображаются в Второе перечислимо. Таким образом, в указанном вами случае результат будет {"Pete", "Joel"}.

В этом случае мышление в терминах строковых массивов, возможно, представляет собой красную сельдь. Возможно, было бы более выгодно думать с точки зрения равенства объектов (http://msdn.microsoft.com/en-us/library/system.object.equals.aspx).

Документация Microsoft находится здесь: http://msdn.microsoft.com/en-us/library/system.linq.enumerable.except.aspx

...