IComparable solo funciona de una manera
Digamos que tienes una Employeeclase. En una vista, desea mostrar todo Employeesordenado 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 Customerordenado por nombre, no hay ningún código que implique cómo se va a ordenar.
Por otro lado, la Customerclase 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 Customerclase, 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 IComparableimplementació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 IComparableen 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 IComparableinferior IComparero .OrderBy(), hasta el punto de no ver ningún caso de uso válido que las alternativas no sirvan mejor.
¿Siempre es mejor usar IComparero LINQ, o hay ventajas / casos de uso que no estoy viendo aquí?
fuente

IComparablemás, lo que está reforzando mi punto.SortedXXXcolecciones, requieren que los elementos almacenados seanIComparableo que seIComparerproporcionen. También tenga en cuenta que es trivial invertir el orden de clasificación natural con un comparador y hacer que funcione con todos losIComparableobjetos.IComparablese considera el mecanismo de comparación predeterminado .IComparerse usa cuando desea anular el mecanismo de comparación predeterminado.ReverseComparer<T>: gist.github.com/jackfarrington/078e7af7bc82482aa634Respuestas:
IComparabletiene 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
OrderBytodo 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.IComparableimplementació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 porqueIComparableera 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
IComparableSolo mira los comentarios sobre
Array.Sort()IComparableinterfaz 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