Почему бы не разрешить реализацию интерфейса на месте в .NET? - PullRequest
13 голосов
/ 04 мая 2011

Либо я что-то упустил, либо .NET не поддерживает то, что делает Java.Я хотел бы иметь возможность избежать создания небольшого класса только для реализации небольшого интерфейса.Например, метод Except в LINQ ожидает IEqualityComparer.Поэтому мне пришлось написать небольшой класс, который реализует интерфейс.Однако в Java я могу просто сделать new IEqualityComparer() { //interface declarations } и покончить с этим.Так в чем проблема?

Это как-то связано с этим постом:

Может ли анонимный класс C # реализовать интерфейс? .

ДОПОЛНЕНИЕ: На данный момент я добавилпереопределяет для Equals и GetHashCode.

Ответы [ 2 ]

14 голосов
/ 04 мая 2011

Вы правы, C #, в отличие от Java, не поддерживает понятие анонимных внутренних классов, которые могут реализовывать интерфейсы.Я столкнулся с точно такой же проблемой с IEqualityComparer и в итоге пришел к следующему решению.

public static class Utils {
  private sealed class EqualityComparer<T> : IEqualityComparer<T> {
    private readonly Func<T, T, bool> m_equals;
    private readonly Func<T, int> m_getHashCode;
    internal EqualityComparer(
      Func<T, T, bool> equals,
      Func<T, int> getHashCode) {
      m_equals = equals;
      m_getHashCode = getHashCode;
    }
    public bool Equals(T left, T right) {
      return m_equals(left, right);
    }
    public int GetHashCode(T value) {
      return m_getHasheCode(value);
    }
  }

  public static IEqualityComparer<T> CreateEqualityComparer<T>(
    Func<T, T, bool> equals, 
    Func<T, int> getHashCode) {
    return new EqualityComparer<T>(equals, getHashCode);
  }
}

Теперь в местах, где я хочу на лету IEqualityComparer<T> я могу просто сделать следующее

var comparer = Utils.CreateEqualityComparer<Student>(
  (left, right) => left.Name == right.Name,
  value => value.Name.GetHashCode());
4 голосов
/ 04 мая 2011

Короткий ответ: это не поддерживается в C # .Net

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

Для этого конкретного примера естьразбросанные посты в блогах, в которых есть реализация для LambdaComparer (или аналогичного), которая позволяет вам делать это, хотя и с использованием несколько менее элегантного синтаксиса.См. Передача лямбда-выражения вместо IComparer, IEqualityComparer или любого однопроцессного интерфейса? для примера.

...