C# - Interface IComparer
Hoje veremos a interface IComparer da linguagem C#. |
As interfaces IComparable e IComparer embora tenham nomes parecidos servem a diferentes propósitos.
Se você tiver uma coleção que já dá suporte a IComparer você vai poder ordenar a coleção sem precisar fornecer nenhuma referência explícita a IComparer. Nestes casos os elementos da coleção são convertidos para a implementação padrão de IComparer (Comparer.Default). No entanto, se você deseja fornecer capacidade de classificação ou comparação para seus objetos personalizados, deve implementar uma ou ambas as interfaces.
IComparer
A interface IComparer fornece o método Compare que compara dois objetos e retorna um valor indicando se um é menor, igual ou maior que o outro.
Obs: O método CompareTo da interface IComparable pode classificar usando apenas um campo por vez, portanto, não é possível classificar propriedades diferentes com ele.
Assim, a função de IComparer é fornecer mais mecanismos de comparação. Por exemplo, talvez você queira fornecer a ordem de sua classe em vários campos ou propriedades, ordem crescente e decrescente no mesmo campo ou ambos.
Essa interface é usada com os métodos List.Sort e List.BinarySearch, e fornece uma maneira de personalizar a ordem de classificação de uma coleção. As classes SortedDictionary e SortedList implementam essa interface.
Vejamos um exemplo de uso desta interface.
Suponha que temos uma lista de funcionários com salários e que desejamos ordenar a lista pelo valor dos salários.
var
funcionarios =
new
List<(string,
int)> { ("José Antunes ", 1230), ("Adam Nunes", 670), ("Roberto Caiado", 2300), ("Rose Amado", 990), ("Jaime Santos", 1190), ("Janete Bueno", 980), ("Lucia Silveira", 980), ("Tomas Sanches", 1400) }; |
Aqui estamos usando uma tupla que é uma estrutura de dados que contém uma sequenência de elementos de diferentes tipos. A classe Tuple() fornece métodos estáticos para criar objetos de coleção de itens.
Se aplicarmos o método Sort() veremos que a ordenação vai ser feita pelo nome do funcionário pois estamos usando o comparador padrão.
funcionarios.Sort();
funcionarios.ForEach(funci => Console.WriteLine(funci));
Assim teremos que usar a interface IComparer e implementar o método Compare onde vamos definir a ordenação com base no salário do funcionário.
Vamos criar para isso a classe SalarioComparer :
class
SalarioComparer : IComparer<(string,
int)> { public int Compare((string, int) funci1, (string, int) funci2) { return funci1.Item2.CompareTo(funci2.Item2); } } |
A seguir podemos usar o construtor Sort(new SalarioComparer) e passar a instância de SalarioComparer onde temos a comparação por salário implementada :
var funcionarios = new List<(string, int)>
{
("José Antunes ", 1230),
("Adam Nunes", 670),
("Roberto Caiado", 2300),
("Rose Amado", 990),
("Jaime Santos", 1190),
("Janete Bueno", 980),
("Lucia Silveira", 980),
("Tomas Sanches", 1400)
};
funcionarios.Sort(new SalarioComparer());
Console.WriteLine("Ordem salarial\n");
funcionarios.ForEach(funci => Console.WriteLine(funci));
Console.ReadKey();
class SalarioComparer : IComparer<(string, int)>
{
public int Compare((string, int) funci1, (string, int) funci2)
{
return funci1.Item2.CompareTo(funci2.Item2);
}
}
|
O resultado obtido é dado abaixo:
Os métodos Order e OrderDescending da LINQ possuem variantes sobrecarregadas que usam o IComparer como parâmetro como mostra o exemplo a seguir:
var
palavras =
new List<string>
{ "Mundo", "Guerra", "Livro", "Casa", "floresta", "oceano", "Viveiro", "faca" }; Console.WriteLine( "\nLinq - Order\n");var linqOrder = palavras.Order(StringComparer.OrdinalIgnoreCase).ToList(); linqOrder.ForEach(palavra => Console.WriteLine(palavra)); Console.WriteLine( "\nLinq - OrderDescending\n");var linqOrderDescending = palavras.OrderDescending(StringComparer.OrdinalIgnoreCase).ToList(); linqOrderDescending.ForEach(w => Console.WriteLine(w)); Console.ReadKey(); |
Observe que estamos passando StringComparer.OrdinalIgnoreCase para os métodos.
StringComparer é um comparador embutido para comparar strings que representa uma operação de comparação de cadeia de caracteres que usa casos específicos e regras de comparação ordinal ou baseadas em cultura.
E estamos conversados...
"E vi um novo céu, e uma nova terra. Porque já o primeiro céu e a primeira
terra passaram, e o mar já não existe."
Apocalipse 21:1
Referências:
NET - Unit of Work - Padrão Unidade de ...