Как я могу заставить компилятор C # выводить эти параметры типа автоматически? - PullRequest
1 голос
/ 18 мая 2010

У меня есть код, который выглядит следующим образом.Сначала у меня есть несколько классов доменов и некоторые специальные компараторы для них.

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());

Очевидно, это огромная проблемаи это не очень СУХОЙ.Что я могу изменить здесь, чтобы мне не приходилось писать параметры типа явно?

Ответы [ 2 ]

2 голосов
/ 18 мая 2010

Попробуйте просто указать T без U и V, как это.

public static bool SemanticSequenceEquals<T>(
    IEnumerable<T> lhs, 
    IEnumerable<T> rhs, 
    IEqualityComparer<T> comparator)
{
    return SemanticEquals(lhs, rhs, (l, r) => lhs.SequenceEqual(rhs, comparator));
}
1 голос
/ 18 мая 2010

Вы можете явно ввести свои аргументы в SemanticSequenceEquals Кажется, это хорошо для меня:

public static bool SemanticSequenceEquals<T>(IEnumerable<T> lhs, IEnumerable<T> rhs, IEqualityComparer<T> comparator)
{
    return SemanticEquals(lhs, rhs, (l, r) => lhs.SequenceEqual(rhs, comparator));
}

List<Fruit> a, b;
return ConstraintChecker.SemanticSequenceEquals(a, b, new FruitEqualityComparer());
...