¿Debo implementar tanto IComparable
como el genérico IComparable<T>
? ¿Hay alguna limitación si solo implemento uno de ellos?IComparable e IComparable <T>
Respuesta
Sí, debe implementar ambos.
Si implementa uno, cualquier código que dependa del otro fallará.
Hay un montón de código que usa ya sea IComparable
o IComparable<T>
pero no ambos, por lo tanto, la implementación de ambos garantiza que su código funcionará con dicho código.
Si controla todo el código, ¿puede determinar que solo necesita implementar la versión genérica? ¿O parte del código de marco aún requiere la versión no genérica? –
@David, algunas clases de marco (por ejemplo, colecciones) pueden basarse en una u otra. –
@David - 'IComparable' ciertamente es usado por algún código de framework. Creo que 'Array.Sort' y' ArrayList.Sort' lo usan. – Oded
Mientras IEquatable <T> generalmente no debería ser implementada por clases sin sellar, ya que tal derivación jugaría curiosamente con la herencia a menos que la aplicación simplemente llama Object.equals (en cuyo caso no tendría sentido), la situación contraria surge con la genérico IComparable <T>. La semántica de Object.Equals e IEquatable <T> implica que siempre que se defina IEquatable <T>, su comportamiento debe reflejar el de Object.Equals (además de ser posiblemente más rápido y evitar el boxeo). Dos objetos de tipo DerivedFoo que se comparan como iguales cuando se los considera como tipo DerivedFoo también deben comparar iguales cuando se consideran objetos del tipo Foo, y viceversa. Por otro lado, es completamente posible que dos objetos de tipo DerivedFoo que se clasifican de manera desigual cuando se consideran como tipo DerivedFoo se clasifiquen por igual cuando se los considere como tipo Foo. La única manera de asegurar esto es usar IComparable <T>.
Supongamos, por ejemplo, que uno tiene una clase SchedulerEvent que contiene los campos ScheduledTime (de tipo DateTime) y ScheduledAction (de tipo MethodInvoker). La clase incluye los subtipos SchedulerEventWithMessage (que agrega un campo de mensaje de tipo string) y SchedulerEventWithGong (que agrega un campo GongVolume de tipo Double). La clase SchedulerEvent tiene un orden natural, por ScheduledTime, pero es completamente posible que los eventos que están desordenados uno con respecto al otro sean desiguales. Las clases SchedulerEventWithMessage y SchedulerEventWithGong también tienen un orden natural entre ellos, pero no cuando se comparan con elementos de la clase SchedulerEvent.
Supongamos que uno tiene dos eventos SchedulerEventWithMessage X e Y programados para el mismo tiempo, pero X.Message es "aardvark" e Y.Message es "zymurgy". ((IComparable <SchedulerEvent>) X) .CompareTo (Y) debe informar cero (dado que los eventos tienen tiempos iguales) pero ((IComparable <SchedulerEventWithMessage>) X) .CompareTo (Y) debe devolver un número negativo (ya que "aardvark" tipo antes de "zymurgy"). Si la clase no se comportó de esa manera, sería difícil o imposible ordenar de manera consistente una lista que contenga una mezcla de objetos SchedulerEventWithMessage y SchedulerEventWithGong.
Dicho sea de paso, se podría argumentar que sería útil tener la semántica de IEtabletable <T> comparando objetos solo en la base de los miembros de tipo T, de modo que, p. IEtabletable <SchedulerEvent> comprobará ScheduledTime y ScheduledAction para la igualdad, pero incluso cuando se aplica a un SchedulerEventWithMessage o SchedulerEventWithGong no verificaría las propiedades Message o GongVolume. De hecho, esas serían semánticas útiles para un método de 0tablecimiento < de IE, y yo preferiría esa semántica, pero para un problema: Comparer <T> .Default.GetHashCode (T) siempre llama a la misma función Object.GetHashCode() independientemente de tipo T. Esto limita en gran medida la capacidad de IEtabletable <T> para variar su comportamiento con diferentes tipos T.
Muy interesante respuesta. –
Oded tiene razón en que debe implementar ambos porque hay colecciones y otras clases que dependen de una sola de las implementaciones.
Pero hay un truco allí: IComparable <T> no debería arrojar excepciones, mientras que IComparable debería. Al implementar IComparable <T>, usted se encarga de garantizar que todas las instancias de T se puedan comparar entre sí. Esto incluye nulo, también (tratar nulo como más pequeño que todas las instancias no nulas de T y estarás bien).
Sin embargo, general IComparable acepta System.Object y no puede garantizar que todos los objetos imaginables sean comparables contra instancias de T. Por lo tanto, si obtiene una instancia no T pasada a IComparable, simplemente ejecute System.ArgumentException . De lo contrario, enrute la llamada a la implementación de IComparable <T>.
Aquí está el ejemplo:
public class Piano : IComparable<Piano>, IComparable
{
public int CompareTo(Piano other) { ... }
...
public int CompareTo(object obj)
{
if (obj != null && !(obj is Piano))
throw new ArgumentException("Object must be of type Piano.");
return CompareTo(obj as Piano);
}
}
Este ejemplo es parte de un artículo mucho más largo que contiene un amplio análisis de los efectos secundarios que se debe tener cuidado de la hora de implementar IComparable <T>: How to Implement IComparable<T> Interface in Base and Derived Classes
- 1. genéricos e implementar IComparable
- 2. Ejecución IComparable <T>
- 3. Int32? con IComparable
- 4. IComparable y equals()
- 5. ¿Cuál es la diferencia entre las interfaces IComparable e IEquatable?
- 6. restricción de interfaz para IComparable
- 7. elemento de Max/Min sin utilizar IComparable <T>
- 8. Al menos un objeto debe implementar IComparable
- 9. ¿Cómo implementar la interfaz de IComparable?
- 10. IComparable algunos de los cuales son nulos
- 11. implementando la interfaz IComparable en dos campos de cadena
- 12. Tipo genérico anulable utilizado con IComparable. ¿Es posible?
- 13. C# cómo ordenar una lista sin implementar IComparable manualmente?
- 14. ¿Por qué IEnumerable <T> .Max no obliga a ser IComparable?
- 15. C# BinarySearch se rompe al heredar de algo que implementa IComparable <T>?
- 16. C# - ¿Cómo implementar múltiples comparadores para una clase de IComparable <T>?
- 17. ¿Por qué la lista <T>. Método de ordenar reordenar elementos iguales de IComparable <T>?
- 18. ¿Por qué List <>. OrderBy LINQ es más rápido que IComparable + List <>. ¿Ordenar en modo Debug?
- 19. ¿Cómo hacer una clase base abstracta IComparable que no compare dos clases heredadas por separado?
- 20. Tengo un problema con IComparable y el método de ordenación de colecciones
- 21. ¿Cómo puedo usar "es" para probar si un tipo admite IComparable?
- 22. "Al menos un objeto debe implementar IComparable" para un INT? Por lo que sé, hace
- 23. ¿Por qué no son genéricos IStructuralEquatable e IStructuralComparable?
- 24. ¿Para qué es la clase Comparer <T>?
- 25. Lista <T> Ordenar utiliza Comparer <T> en lugar de IEquatable, ¿Por qué?
- 26. ¿Cuál es la diferencia entre <? super E> y <? extends E>?
- 27. <T & E se extiende Objeto> vs <T extends E>
- 28. ¿Qué es estático <E>?
- 29. StructureMap e inyección IEnumerable <T>
- 30. Utilidad de ArrayList <E> .clear()?
Solo necesita escribir el código para 'IComparable'. Obtienes 'IComparable' de forma gratuita al delegar las comparaciones reales a la (s) implementación (es) genérica (s). –