IComparable
só funciona de uma maneira
Digamos que você tenha uma Employee
aula. Em uma exibição, você deseja mostrar todas as Employees
ordenadas por nome - em outra, por endereço. Como você vai conseguir isso? Não com IComparable
, pelo menos não de maneira idiomática.
IComparable
tem a lógica no lugar errado
A interface é usada chamando .Sort()
. Em uma exibição que mostra Customer
classificada por nome, não há nenhum código que implique como será classificado.
Por outro lado, a Customer
classe está assumindo como será usada - nesse caso, que será usada em uma lista classificada por nomes.
IComparable
é usado implicitamente
Em comparação com as alternativas, é muito difícil ver onde a lógica de comparação está sendo usada - ou se é que existe. Supondo que seu IDE padrão e a partir da Customer
classe, terei que
- Pesquise todas as referências a
Customer
- Encontre as referências usadas em uma lista
- Verifique se essas listas já os
.Sort()
chamaram
O que é provavelmente pior, se você remover uma IComparable
implementação que ainda está sendo usada, você não receberá nenhum erro ou aviso. A única coisa que você terá é o comportamento errado em todos os lugares que eram muito obscuros para você pensar.
Essas questões combinadas, além de requisitos variáveis
O motivo pelo qual eu vim a pensar sobre isso é porque deu errado para mim. Felizmente, uso IComparable
meu aplicativo há 2 anos. Agora, os requisitos foram alterados e a coisa precisa ser classificada de duas maneiras diferentes. Percebeu que não é divertido seguir as etapas descritas na seção anterior.
A questão
Esses problemas me fazem pensar IComparable
como inferior a IComparer
ou .OrderBy()
, a ponto de não ver nenhum caso de uso válido que não seria melhor atendido pelas alternativas.
É sempre melhor usar IComparer
ou LINQ, ou existem vantagens / casos de uso que não estou vendo aqui?
fonte
IComparable
mais, o que está reforçando meu argumento.SortedXXX
coleções, elas exigirão que os elementos armazenados sejamIComparable
ou sejamIComparer
fornecidos. Observe também que é trivial reverter a ordem de classificação natural com um comparador e fazê-la funcionar com todos osIComparable
objetos.IComparable
é considerado o mecanismo de comparação padrão .IComparer
é usado quando você deseja substituir o mecanismo de comparação padrão.ReverseComparer<T>
: gist.github.com/jackfarrington/078e7af7bc82482aa634Respostas:
IComparable
tem as restrições que você mencionou, isso está correto. É uma interface que já estava disponível no .NET Framework 1.0, onde essas alternativas funcionais e o Linq não estavam disponíveis. Então, sim, pode-se vê-lo como um elemento de estrutura desatualizado que é mantido principalmente para compatibilidade com versões anteriores.No entanto, para muitas estruturas simples de dados, uma maneira de classificar é provavelmente suficiente ou natural. Nesses casos, ter um local canônico para implementar o relacionamento do pedido ainda é uma boa maneira de manter o código DRY, em vez de sempre repetir a mesma lógica em todas as chamadas para
OrderBy
todo o local.Você está "felizmente usando o IComparable em seu aplicativo há 2 anos", como escreveu, portanto, parece-me que serviu bem por um longo tempo. Quando você agora precisa validar, alterar e testar todas as chamadas
Sort
, também pode ser um sinal de que você estava fazendo o mesmo tipo de lógica de classificação em muitos lugares, o que não é culpa deleIComparable
. Portanto, essa pode ser uma ocasião para centralizar mais essa lógica em um só lugar, tornando seu código mais SECO.fonte
IComparable
, todo o código de classificação preexistente teria sido deixado intocado em suas respectivas visualizações, enquanto eu adicionaria apenas um novo código de classificação para a nova exibição.IComparable
implementação que você escreveu?IComparable
, você obtém uma implementação padrão de graça e, às vezes, nem precisa escrever essa implementação.BigInteger
. Se não implementasse operadores / interfaces de comparação, como você implementaria um IComparer ? Você precisaria acessar as estruturas de dados internas para fazê-lo com eficiência, ou de todo. Suponha que você tenha um tipo como Cliente; as propriedades públicas que você deseja classificar tarefas têm comparadores. Para mim, essa é a diferença: implementeIComparable<T>
se não for razoável esperar que o chamador implemente um 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.
Só porqueIComparable
era uma solução melhor na época , não significa que é a melhor solução hoje . Seu primeiro comentário aqui implica que "é IComparable ou nada", o que não é verdade, o problema poderia ter sido resolvido de várias maneiras diferentes. Os aplicativos podem crescer em tamanho / escala, e coisas que costumavam parecer adequadas podem não ser capazes de acompanhar as crescentes demandas do aplicativo.Eu concordo com seus sentimentos sobre
IComparable
Basta olhar para as observações em
Array.Sort()
IComparable
interface para poder comparar com todos os outros elementos da matriz. (ou exceção é lançada)Provavelmente nunca iremos agora a motivação, no entanto! considere
object.Equals()
um método para cada objeto que permita comparar objetos entre si para ver se eles são "iguais"Você já o possui, mas recebeu a tarefa de adicionar.
Array.Sort()
Você pode adicionarobject.Compare(object)
fonte