Pregunta

O me falta algo o .NET no admite lo que hace Java. Me gustaría poder evitar crear una clase pequeña solo para implementar una pequeña interfaz. Por ejemplo, el método de Linq excepto el método IEqualityComparer. Así que tuve que escribir una clase pequeña que implementa la interfaz. Sin embargo, en Java simplemente puedo hacer un new IEqualityComparer() { //interface declarations } y terminar con eso. ¿Entonces, cuál es el problema?

Esto está algo relacionado con esta publicación:

¿Puede una clase anónima C# implementar una interfaz?.

Adición: en este momento, agregué anulaciones para Equals y GetHashCode.

¿Fue útil?

Solución

Tienes razón, C# a diferencia de Java, no admite la noción de clases internas anónimas que pueden implementar interfaces. Me he encontrado con exactamente el mismo problema con IEqualityComparer y finalmente llegó a la siguiente solución.

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

Ahora en lugares donde quiero una mosca IEqualityComparer<T> Puedo hacer lo siguiente

var comparer = Utils.CreateEqualityComparer<Student>(
  (left, right) => left.Name == right.Name,
  value => value.Name.GetHashCode());

Otros consejos

La respuesta corta es que esto no es compatible con C# .net

Tengo que admitir que suena bastante bueno, pero normalmente esto no es realmente necesario. Los métodos de comparación en LINQ parecen ser la excepción, la mayoría de los otros métodos LINQ aceptan sobrecargas que realizan lo mismo usando delegados, que pueden implementarse "en el lugar" a través de expresiones Lambda.

Para este ejemplo específico, hay una dispersión de publicaciones de blog que tienen una implementación para un LambdaComparer (o similar) que le permite hacer exactamente esto, aunque use una sintaxis algo menos elegante. Ver ¿Pase una expresión de lambda en lugar de iComParer o iEqualityComparer o cualquier interfaz de un solo método? para un ejemplo.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top