У меня есть код, который выглядит следующим образом.Сначала у меня есть несколько классов доменов и некоторые специальные компараторы для них.
public class Fruit {
public int Calories { get; set; }
public string Name { get; set; }
}
public class FruitEqualityComparer : IEqualityComparer<Fruit> {
// ...
}
// A basket is just a group of Fruits.
public class BasketEqualityComparer : IEqualityComparer<IEnumerable<Fruit>> {
// ...
}
Далее у меня есть вспомогательный класс с именем ConstraintChecker
.Он имеет простой метод BaseEquals
, который обеспечивает рассмотрение некоторых простых базовых случаев:
public static class ConstraintChecker {
public static bool BaseEquals(T lhs, T rhs) {
bool sameObject = l == r;
bool leftNull = l == null;
bool rightNull = r == null;
return sameObject && !leftNull && !rightNull;
}
Также существует метод SemanticEquals
, который представляет собой просто проверку BaseEquals
и указанную вами функцию сравнения.
public static bool SemanticEquals<T>(
T lhs, T rhs, Func<T, T, bool> f) {
return BaseEquals(lhs, rhs) && f(lhs, rhs);
}
И, наконец, есть метод SemanticSequenceEquals
, который принимает для сравнения два экземпляра IEnumerable<T>
, и экземпляр IEqualityComparer, который будет вызываться для каждой пары элементов в списке с помощью Enumerable.SequenceEquals
.
public static bool SemanticSequenceEquals<T, U, V>(U lhs,
U rhs,
V comparator)
where U : IEnumerable<T>
where V : IEqualityComparer<T> {
return SemanticEquals(lhs, rhs, (l, r) => lhs.SequenceEqual(rhs, comparator));
}
} // end of ConstraintChecker
Смысл SemanticSequenceEquals
в том, что вам не нужно определять два компаратора, когда вы хотите сравнить оба экземпляра IEnumerable<T>
и T
;теперь вы можете просто указать IEqualityComparer<T>
, и он также будет обрабатывать списки при вызове SemanticSequenceEquals
.Так что я мог бы избавиться от класса BasketEqualityComparer, что было бы неплохо.
Но есть проблема.Компилятор C # не может определить типы, задействованные при вызове SemanticSequenceEquals:
// Error! Compiler can't infer the type parameters.
return ConstraintChecker.SemanticSequenceEquals(lhs, rhs,
new FruitEqualityComparer());
Если я укажу их явно, это сработает:
return ConstraintChecker.SemanticSequenceEquals<Fruit, IEnumerable<Fruit>,
IEqualityComparer<Fruit>> (lhs, rhs, new FruitEqualityComparer());
Очевидно, это огромная проблемаи это не очень СУХОЙ.Что я могу изменить здесь, чтобы мне не приходилось писать параметры типа явно?