2009-09-30 11 views
6

I tiene un modelo de dominio que se trivialmente representado por la siguiente.Ejecución IEquatable <T> donde T es una interfaz

IMyInterface 

ClassA : IMyInterface 

ClassB : IMyInterface 

Lo que quiero es implementar IEquatable de forma que pueda escribir código como este.

if(dynamicallyCreatedInstanceOfClassA == dynamicallyCreatedinstanceOfClassB) 
{ 
    // Do something relevant 
} 

Mi primera inclinación era tener IMyInterface implementar IEquatable pero por supuesto que no se puede hacer realidad la implementación de IMyInterface. Tendría que hacer eso en ClassA y ClassB. Lo que me parece erróneo con esta solución es que las implementaciones de IEquatable en ClassA y ClassB serán exactamente, línea por línea, lo mismo. ¿Hay una forma elegante de lograr esto? Cuando aparezca ClassC, no quiero tener que copiar y pasar 50 líneas de código IEquatable duplicado.

he considerado el uso de una clase base abstracta en lugar de una interfaz, pero en este escenario IMyInterface realidad sólo describe las acciones de la clase llevará a cabo y no lo que la clase es. ClassA y ClassB no comparten muchas similitudes, excepto que ambos pueden realizar las acciones en el contrato de IMyInterface.

Cualquier información es útil, y gracias por su tiempo.

+0

que habría sugerido a seguir el camino abstracto también, pero el inconveniente es que que van a limitar sus clases derivadas de heredar de otra clase concreta como MI no está permitido en C#.Consulte la respuesta de supercat para ver el problema potencial relacionado con 'GetHashCode'. El enfoque de Jon es la única salida fácil que parece ... – nawfal

+1

@nawfal: el enfoque de Jon es el correcto, ya que es completamente normal y se espera que un 'IEqualityComparer ' represente formas bastante amplias de equivalencia, que' T' puede no saber nada acerca de. Por ejemplo, dos objetos que implementen 'IList ' probablemente solo se den a conocer como iguales si siempre contendrán los mismos elementos en el mismo orden. Sin embargo, puede ser útil que un objeto pueda almacenar las listas que posee en un 'Diccionario , cualquiera'>, donde las listas que contienen los mismos elementos en cualquier secuencia se compararán idénticas. – supercat

+1

@nawfal: No existe tal método de comparación en 'IList '; las implementaciones generalmente tampoco proporcionan una. No obstante, dicho método de comparación puede ser útil en algunos contextos, por lo que sería perfectamente razonable utilizar una clase externa para implementar un 'ICEqualityComparer >' de esa manera. – supercat

Respuesta

7

En lugar de implementar IEquatable<T>, ¿podría implementar IEqualityComparer<T> en una clase separada? En la mayoría de los casos en los que le interesa la igualdad, puede especificar un comparador en su lugar, y sospecho que será más limpio de esa manera.

+0

Esa es una buena idea Jon, gracias por la entrada. Acabo de leer C# en profundidad, y me ha enseñado mucho sobre el lenguaje que ni siquiera había considerado antes. Lo leeré por segunda vez inmediatamente solo para tratar de empaparlo todo. –

+0

@Matthew: Es posible que desee esperar hasta que la segunda edición esté lista para una segunda lectura; de lo contrario, tendrá que leerlo todo * tres * veces :) –

+0

Ese es un buen punto, ¿qué es el eta en la segunda edición? –

0

Me gustaría pensar que si la interfaz no se puede convertir a una clase abstracta, no tiene mucho sentido que la comparación de las dos clases implementadas entre sí directamente o de forma automática. Lo que significa que la implementación de una comparación personalizada en cada clase sería el camino a seguir. Estoy seguro de que puede refactorizar el código de comparación de alguna manera para facilitar el cambio más adelante.

5

Sobre la base de su pregunta parece que usted sabe lo que el algoritmo de Iguales será y que va a ser exactamente el mismo para ambos Clase A ni ClassB. ¿Por qué no hacer lo siguiente

  1. Definir IMyInterface heredar de IEquatable<IMyInterface>
  2. Definir una MyInterfaceBase clase base abstracta que implementa IMyInterface y tiene la IEquatable<IMyInterface> aplicación
  3. Tienes Clase A ni ClassB derivan de MyInterfaceBase
+0

Lo he considerado también, he temido que la clase A necesite heredar en el futuro cercano para lograr otros objetivos, por supuesto puedo cruzar ese puente cuando llegue a él, si voy a seguir este camino También puedo cortar la interfaz y usar una clase base abstracta. No está fuera de la cuestión tampoco. Gracias por el aporte. –

1

Si IEquatable<T> incluido un miembro de GetHashcode() que podría ser posible definir una semántica significativa para ese tipo que se diferenciaba de Object.Equals (por ejemplo, "si uno buscando sólo a las características que están presentes en T, serían considerados el mismo los objetos") Sin embargo, dado que no es así, generalmente no hay muchas razones para implementar IEquatable<T>, excepto en aquellos casos en los que puede mejorar el rendimiento sin agregar ninguna semántica peculiar. En la práctica, eso significa que IEquatable<T> solo debe implementarse por T (si T es una clase o estructura sellada), o no (si T es heredable, o si los beneficios de rendimiento no justifican el esfuerzo).

+0

+1 para realmente abordar el problema .. – nawfal

Cuestiones relacionadas