IComparer para classificação personalizada
Forneça ordenações alternativas com comparadores.
IComparer para classificação personalizada é uma aula grátis de C# Academy no CoddyKit. Esta é a aula 4 de 4. Você pode ler a aula completa abaixo gratuitamente — depois pratica ao vivo no navegador com um editor de código integrado e um tutor de IA 24/7. Faz parte do caminho de aprendizado de C# Academy, e seu progresso é sincronizado entre a web e o app CoddyKit. O curso de C# Academy inclui 4 aulas no total.
Ordenando de formas diferentes
Um tipo tem apenas uma ordem natural por meio de IComparable<T>. Para ordenar os mesmos dados de outras formas, forneça um IComparer<T> ou um delegado Comparison<T> no local da chamada.
Implementando IComparer<T>
Um IComparer<T> é um objeto separado com um método Compare(x, y). Ele segue o mesmo contrato de valores negativo, zero e positivo que CompareTo.
using System;
using System.Collections.Generic;
public class Person
{
public string Name;
public int Age;
public Person(string name, int age) { Name = name; Age = age; }
public override string ToString() => Name + "(" + Age + ")";
}
public class ByName : IComparer<Person>
{
public int Compare(Person x, Person y)
=> string.Compare(x.Name, y.Name, StringComparison.Ordinal);
}
public class Program
{
public static void Main()
{
var people = new List<Person> { new Person("Zoe", 1), new Person("Ann", 2) };
people.Sort(new ByName());
Console.WriteLine(string.Join(", ", people));
}
}Vários comparadores para um tipo
É possível definir vários comparadores e escolher um para cada ordenação. Aqui, as mesmas people podem ser ordenadas por nome ou por idade conforme necessário.
using System;
using System.Collections.Generic;
public class Person
{
public string Name;
public int Age;
public Person(string name, int age) { Name = name; Age = age; }
public override string ToString() => Name + "(" + Age + ")";
}
public class ByAge : IComparer<Person>
{
public int Compare(Person x, Person y) => x.Age.CompareTo(y.Age);
}
public class Program
{
public static void Main()
{
var people = new List<Person> { new Person("Ann", 40), new Person("Bo", 20) };
people.Sort(new ByAge());
Console.WriteLine(string.Join(", ", people));
}
}Delegado Comparison<T>
Para ordenações pontuais, um delegado Comparison<T> (geralmente uma lambda) é mais conciso do que uma classe inteira. List.Sort o aceita diretamente.
using System;
using System.Collections.Generic;
public class Program
{
public static void Main()
{
var words = new List<string> { "banana", "fig", "apple" };
// Sort by length using a Comparison<string> lambda
words.Sort((a, b) => a.Length.CompareTo(b.Length));
Console.WriteLine(string.Join(", ", words));
}
}Ordem decrescente com um comparador
Inverta uma ordem trocando os operandos dentro de Compare. Isso produz uma ordenação decrescente sem modificar o próprio tipo.
using System;
using System.Collections.Generic;
public class DescendingInt : IComparer<int>
{
public int Compare(int x, int y) => y.CompareTo(x);
}
public class Program
{
public static void Main()
{
var nums = new List<int> { 3, 1, 4, 1, 5 };
nums.Sort(new DescendingInt());
Console.WriteLine(string.Join(", ", nums));
}
}Comparadores em OrderBy
O LINQ OrderBy aceita um IComparer<TKey> como segundo argumento, permitindo personalizar como as chaves selecionadas são comparadas.
using System;
using System.Collections.Generic;
using System.Linq;
public class CaseInsensitive : IComparer<string>
{
public int Compare(string x, string y)
=> string.Compare(x, y, StringComparison.OrdinalIgnoreCase);
}
public class Program
{
public static void Main()
{
var names = new[] { "bob", "Alice", "carol" };
foreach (var n in names.OrderBy(x => x, new CaseInsensitive()))
Console.WriteLine(n);
}
}Comparação por várias chaves
Um comparador pode ordenar por várias chaves na ordem de prioridade. Calcule a primeira chave; se houver empate, passe para a próxima.
using System;
using System.Collections.Generic;
public class Employee
{
public string Dept;
public int Salary;
public Employee(string dept, int salary) { Dept = dept; Salary = salary; }
public override string ToString() => Dept + ":" + Salary;
}
public class ByDeptThenSalary : IComparer<Employee>
{
public int Compare(Employee x, Employee y)
{
int byDept = string.Compare(x.Dept, y.Dept, StringComparison.Ordinal);
return byDept != 0 ? byDept : x.Salary.CompareTo(y.Salary);
}
}
public class Program
{
public static void Main()
{
var staff = new List<Employee>
{
new Employee("IT", 50), new Employee("HR", 40), new Employee("IT", 30)
};
staff.Sort(new ByDeptThenSalary());
Console.WriteLine(string.Join(", ", staff));
}
}Atalho Comparer.Create
Comparer<T>.Create cria um IComparer<T> a partir de uma lambda, combinando a concisão de um delegado com as APIs da interface que exigem um comparador.
using System;
using System.Collections.Generic;
public class Program
{
public static void Main()
{
var byLengthDesc = Comparer<string>.Create((a, b) => b.Length.CompareTo(a.Length));
var words = new List<string> { "hi", "hello", "hey" };
words.Sort(byLengthDesc);
Console.WriteLine(string.Join(", ", words));
}
}Reutilizando comparadores entre coleções
Uma única instância de comparador pode conduzir a ordenação, a pesquisa e os conjuntos ordenados. Defini-la uma vez mantém as regras de ordenação consistentes em todos os lugares onde são usadas.
using System;
using System.Collections.Generic;
public class Program
{
public static void Main()
{
IComparer<int> desc = Comparer<int>.Create((a, b) => b.CompareTo(a));
var set = new SortedSet<int>(desc) { 1, 5, 3 };
Console.WriteLine(string.Join(", ", set));
}
}Escolhendo IComparable ou IComparer
Use IComparable<T> para a única ordem natural incorporada ao tipo. Use IComparer<T> ou Comparison<T> para as várias ordens alternativas e específicas do contexto que você decide no local da chamada.
using System;
using System.Collections.Generic;
public class Program
{
public static void Main()
{
var nums = new List<int> { 5, 2, 8, 1 };
nums.Sort(); // natural ascending (int is IComparable)
Console.WriteLine(string.Join(", ", nums));
nums.Sort((a, b) => b - a); // custom descending via delegate
Console.WriteLine(string.Join(", ", nums));
}
}Experimente por si mesmo
Ordene uma lista de três formas diferentes usando comparadores e uma lambda, tudo isso sem alterar o tipo dos elementos.
using System;
using System.Collections.Generic;
public class Program
{
public static void Main()
{
var words = new List<string> { "pear", "fig", "apple", "kiwi" };
words.Sort(); // natural alphabetical
Console.WriteLine(string.Join(", ", words));
words.Sort((a, b) => a.Length.CompareTo(b.Length)); // by length
Console.WriteLine(string.Join(", ", words));
words.Sort(Comparer<string>.Create((a, b) => b.CompareTo(a))); // reverse alphabetical
Console.WriteLine(string.Join(", ", words));
}
}Verificação rápida
Escolha a abstração de ordenação adequada.
Recapitulação
A ordenação personalizada usa comparadores fornecidos no local da chamada.
IComparer<T>implementaCompare(x, y)com o contrato de valores negativo, zero e positivo.- Delegados
Comparison<T>e lambdas são adequados para ordenações pontuais. Comparer<T>.Createfaz a ponte entre lambdas e a interface.- Use
IComparablepara a ordem natural e comparadores para as ordens alternativas.
Perguntas Frequentes
A aula “IComparer para classificação personalizada” é grátis?
Sim — o texto completo de “IComparer para classificação personalizada” é grátis para ler aqui na web. Para praticá-la interativamente (um editor de código integrado e um tutor de IA 24/7) e desbloquear o restante do curso de C# Academy, atualize para CoddyKit PRO. O curso de C# Academy inclui 4 aulas no total.
O que vou aprender em “IComparer para classificação personalizada”?
Forneça ordenações alternativas com comparadores. Você pratica C# Academy com código prático que executa diretamente no navegador, e um tutor de IA 24/7 responde suas dúvidas enquanto trabalha na aula.
Preciso ter experiência prévia para começar C# Academy?
Nenhuma experiência prévia é necessária. C# Academy no CoddyKit é estruturado para alunos iniciantes até avançados, então você pode começar aqui ou desde o início e aprender no seu ritmo. Esta é a aula 4 de 4.
Quanto tempo leva a aula “IComparer para classificação personalizada”?
A maioria das aulas CoddyKit leva cerca de 5–10 minutos. Cada uma é compacta e interativa, então você faz progresso constante e retoma exatamente de onde parou entre web e app.
Posso escrever e executar código nesta aula de C# Academy?
Sim. Cada aula de C# Academy inclui um editor de código integrado, então você escreve e executa código real direto no navegador e recebe feedback de IA instantaneamente — nenhuma configuração local necessária.
Todas as aulas deste curso
- Implementando IEquatable
- Substituindo GetHashCode
- Implementando IComparable
- IComparer para classificação personalizada