IComparable
solo funciona de una manera
Digamos que tienes una Employee
clase. En una vista, desea mostrar todo Employees
ordenado por nombre, en otra, por dirección. ¿Cómo vas a lograr eso? No con IComparable
, al menos no de ninguna manera idiomática.
IComparable
tiene la lógica en el lugar equivocado
La interfaz se usa llamando .Sort()
. En una vista que muestra Customer
ordenado por nombre, no hay ningún código que implique cómo se va a ordenar.
Por otro lado, la Customer
clase está asumiendo cómo se va a usar, en este caso, que se usará en una lista ordenada por nombres.
IComparable
se usa implícitamente
En comparación con las alternativas, es muy difícil ver dónde se está utilizando la lógica de comparación, o si es que lo está. Asumiendo su IDE estándar y comenzando desde la Customer
clase, tendré que
- Buscar todas las referencias a
Customer
- Encuentra las referencias que se usan en una lista
- Verifique si esas listas las han
.Sort()
llamado alguna vez
Lo que probablemente sea peor, si elimina una IComparable
implementación que todavía se está utilizando, no recibirá ningún error o advertencia. Lo único que obtendrá es un comportamiento incorrecto en todos los lugares que eran demasiado oscuros para que usted piense.
Estos problemas combinados, más requisitos cambiantes
La razón por la que llegué a pensar en esto es porque me salió mal. He estado felizmente usando IComparable
en mi aplicación durante 2 años. Ahora, los requisitos cambiaron y la cosa necesita ser ordenada de 2 maneras diferentes. Se ha dado cuenta de que no es divertido seguir los pasos descritos en la sección anterior.
La pregunta
Estos problemas me hacen pensar que soy IComparable
inferior IComparer
o .OrderBy()
, hasta el punto de no ver ningún caso de uso válido que las alternativas no sirvan mejor.
¿Siempre es mejor usar IComparer
o LINQ, o hay ventajas / casos de uso que no estoy viendo aquí?
fuente
IComparable
más, lo que está reforzando mi punto.SortedXXX
colecciones, requieren que los elementos almacenados seanIComparable
o que seIComparer
proporcionen. También tenga en cuenta que es trivial invertir el orden de clasificación natural con un comparador y hacer que funcione con todos losIComparable
objetos.IComparable
se considera el mecanismo de comparación predeterminado .IComparer
se usa cuando desea anular el mecanismo de comparación predeterminado.ReverseComparer<T>
: gist.github.com/jackfarrington/078e7af7bc82482aa634Respuestas:
IComparable
tiene las restricciones que mencionaste, eso es correcto. Es una interfaz que ya estaba disponible en .NET Framework 1.0, donde esas alternativas funcionales y Linq no estaban disponibles. Entonces, sí, uno podría verlo como un elemento de marco obsoleto que se mantiene principalmente para la compatibilidad con versiones anteriores.Sin embargo, para muchas estructuras de datos simples, una forma de clasificación es probablemente suficiente o natural. Para estos casos, tener un lugar canónico para implementar la relación de pedido sigue siendo una buena manera de mantener el código SECO, en lugar de repetir siempre la misma lógica en cada llamada a
OrderBy
todo el lugar.Usted ha estado "felizmente usando IComparable en su aplicación durante 2 años", como escribió, por lo que me parece que le sirvió durante mucho tiempo. Cuando ahora tiene que validar, cambiar y probar todas las llamadas
Sort
, también puede ser una señal de que estaba haciendo el mismo tipo de lógica de clasificación en muchos lugares, lo cual no es culpa deIComparable
. Entonces, esta podría ser una ocasión para centralizar más de esta lógica en un solo lugar, haciendo que su código sea más SECO.fuente
IComparable
, todo el código de clasificación preexistente se habría dejado intacto en sus respectivas vistas, mientras que solo agregaría un nuevo código de clasificación para la nueva vista.IComparable
implementación que escribió?IComparable
, obtienes una implementación predeterminada de forma gratuita, y a veces ni siquiera tienes que escribir esa implementación.BigInteger
. Si no implementara operadores / interfaces de comparación, ¿cómo implementaría usted mismo un IComparer ? Necesitaría acceso a las estructuras de datos internas para hacerlo de manera eficiente, o para nada. Supongamos que tiene un tipo como Cliente; las propiedades públicas que desea ordenar en tareas tienen comparadores. Para mí esa es la diferencia: implementarIComparable<T>
si no sería razonable esperar que la persona que llama implemente un comparador.If I hadn't used IComparable, all the pre-existing sorting code would have been left untouched in their respective views, while I'd only add new sorting code for the new view.
Solo porqueIComparable
era una mejor solución en ese momento , no significa que sea la mejor solución hoy . Su primer comentario aquí implica que "es IComparable o nada", lo cual no es cierto, el problema podría haberse resuelto de muchas maneras diferentes. Las aplicaciones pueden crecer en tamaño / escala, y las cosas que solían verse adecuadas pueden no ser capaces de satisfacer las crecientes demandas de la aplicación.Estoy de acuerdo con tus sentimientos sobre
IComparable
Solo mira los comentarios sobre
Array.Sort()
IComparable
interfaz para poder realizar comparaciones con cualquier otro elemento de la matriz. (o se lanza una excepción)Probablemente nunca tengamos la motivación, ¡Sin embargo! considere
object.Equals()
un método en cada objeto que le permite comparar objetos entre sí para ver si son "iguales"Ya lo tiene allí, pero se le ha encomendado la tarea
Array.Sort()
de agregar.object.Compare(object)
fuente