Разница между двумя перегрузками Enumerable.Except?

Я пытаюсь понять разницу между двумя перегрузками метода Enumerable.Except, т.е.

  • За исключением (IEnumerable, IEnumerable)
  • За исключением (IEnumerable, IEnumerable, IEqualityComparer)

Очевидно, первое отличие заключается в том, что первая перегрузка использует компаратор проверки на равенство по умолчанию, а другая использует IEqualityComparer, но я могу добиться того же результата с помощью первого метода, реализуя IEquatable (как указано в документации MSDN по методу Except), то зачем нужна эта вторая перегрузка?


person Coder23    schedule 11.12.2014    source источник
comment
Ну, только для тех случаев, когда вы не можете реализовать интерфейс IEquatable по какой-то причине (например, если это не ваш класс), но все же хотите использовать собственный компаратор.   -  person Andy Korneyev    schedule 11.12.2014
comment
Возможно, вы хотите использовать его на 2 IEnuemrable<SomeThirdPartyClass>, но не можете изменить SomeThirdPartyClass, тогда вы должны использовать вторую перегрузку.   -  person Ben Robinson    schedule 11.12.2014
comment
Иногда существует несколько применимых правил равенства для объекта, в зависимости от контекста. IEquatable действительно предоставляет один вариант использования, поэтому в таких ситуациях вам нужно определить альтернативный компаратор и вторую перегрузку Except.   -  person code4life    schedule 11.12.2014


Ответы (1)


Две причины:

  1. Вы можете реализовать IEquatable<T> только для ваших собственных типов... тогда как вы можете указать IEqualityComparer<T> для любого типа, независимо от того, можете ли вы изменить его самостоятельно или нет.

  2. Может быть несколько способов сравнения типа на равенство, но реализация IEquatable<T> позволяет выразить только один из них.

Простым примером всего этого могут быть строки — рассмотрим:

string[] x = { "A", "B", "C" };
string[] y = { "A", "c" };

var bc = x.Except(y);
var justB = x.Except(y, StringComparer.OrdinalIgnoreCase);

Нам могут понадобиться оба результата в разных обстоятельствах, что означает, что мы не можем обработать оба результата с помощью IEquatable<T>... и мы все равно не можем изменить то, как string реализует IEquatable<T>. (Конечно, вы не ограничены StringComparer — вы можете написать компаратор равенства, который, например, просто использует длину строки.)

Это также не относится к LINQ - это обычно относится к любому API, который имеет дело с равенством, например. HashSet<>, Dictionary<,> и т. д.

person Jon Skeet    schedule 11.12.2014
comment
Спасибо, Джон! Очень хорошо объяснил :) - person Coder23; 11.12.2014