Usar as IComparable interfaces e IComparer no Visual CSharp

Este artigo descreve o uso de IComparer interfaces e IComparable no Visual C#.

Versão original do produto: Visual C#
Número de KB original: 320727

Resumo

As IComparable interfaces e IComparer são discutidas no mesmo artigo por dois motivos. Essas interfaces são frequentemente usadas juntas. Embora as interfaces sejam semelhantes e tenham nomes semelhantes, elas servem a propósitos diferentes.

Se você tiver uma matriz de tipos (como cadeia de caracteres ou inteiro) que já dá suporte IComparer, poderá classificar essa matriz sem fornecer nenhuma referência explícita a IComparer. Nesse caso, os elementos da matriz são lançados para a implementação padrão de IComparer (Comparer.Default) para você. No entanto, se você quiser fornecer capacidade de classificação ou comparação para seus objetos personalizados, você deve implementar uma ou ambas as interfaces.

Este artigo faz referência ao namespace System.Collectionsda Biblioteca de Classes do Microsoft .NET Framework .

IComparable

A função de IComparable é fornecer um método de comparação de dois objetos de um tipo específico. É necessário se você quiser fornecer qualquer funcionalidade de ordenação para seu objeto. Considere como fornecer uma ordem de IComparable classificação padrão para seus objetos. Por exemplo, se você tiver uma matriz de objetos do seu tipo e chamar o Sort método nessa matriz, IComparable fornecerá a comparação de objetos durante o tipo. Ao implementar a IComparable interface, você deve implementar o CompareTo método da seguinte maneira:

// Implement IComparable CompareTo method - provide default sort order.
int IComparable.CompareTo(object obj)
{
   Car c=(Car)obj;
   return String.Compare(this.make,c.make);
}

A comparação no método é diferente dependendo do tipo de dados do valor que está sendo comparado. String.Compare é usado neste exemplo porque a propriedade escolhida para a comparação é uma cadeia de caracteres.

IComparer

A função de é fornecer mais mecanismos de IComparer comparação. Por exemplo, talvez você queira fornecer ordenação de sua classe em vários campos ou propriedades, ordem crescente e decrescente no mesmo campo ou ambos.

Usar IComparer é um processo de duas etapas. Primeiro, declare uma classe que implemente IComparere implemente o Compare método:

private class SortYearAscendingHelper : IComparer
{
   int IComparer.Compare(object a, object b)
   {
      Car c1=(Car)a;
      Car c2=(Car)b;
      if (c1.year > c2.year)
         return 1;
      if (c1.year < c2.year)
         return -1;
      else
         return 0;
   }
}

Observação

O IComparer.Compare método requer uma comparação terciária. 1, 0 ou -1 é retornado dependendo se um valor é maior que, igual ou menor que o outro. A ordem de classificação (crescente ou descendente) pode ser alterada alternando os operadores lógicos neste método.

A segunda etapa é declarar um método que retorna uma instância do objeto IComparer :

public static IComparer SortYearAscending()
{
   return (IComparer) new SortYearAscendingHelper();
}

Neste exemplo, o objeto é usado como o segundo argumento quando você chama o método sobrecarregado Array.Sort que aceita IComparer. O uso de IComparer não se limita a matrizes. Ele é aceito como um argumento em muitas classes de coleção e controle diferentes.

Exemplo passo a passo

O exemplo a seguir demonstra o uso dessas interfaces. Para demonstrar IComparer e IComparable, uma classe nomeada Car é criada. O Car objeto tem as propriedades make e year. Uma classificação crescente para o campo make é habilitada por meio da IComparable interface e uma classificação decrescente no campo make é habilitada por meio da IComparer interface. As classificações crescentes e descendentes são fornecidas para a propriedade do ano usando IComparer.

  1. No Visual C#, crie um novo projeto de Aplicativo de Console. Nomeie o aplicativo ConsoleEnum.

  2. Renomeie Program.cs como Host.cs e substitua o código pelo código a seguir.

    using System;
    
    namespace ConsoleEnum
    {
        class host
        {
           [STAThread]
           static void Main(string[] args)
           {
              // Create an array of Car objects.
              Car[] arrayOfCars= new Car[6]
              {
                 new Car("Ford",1992),
                 new Car("Fiat",1988),
                 new Car("Buick",1932),
                 new Car("Ford",1932),
                 new Car("Dodge",1999),
                 new Car("Honda",1977)
              };
    
              // Write out a header for the output.
              Console.WriteLine("Array - Unsorted\n");
    
              foreach(Car c in arrayOfCars)
                 Console.WriteLine(c.Make + "\t\t" + c.Year);
    
              // Demo IComparable by sorting array with "default" sort order.
              Array.Sort(arrayOfCars);
              Console.WriteLine("\nArray - Sorted by Make (Ascending - IComparable)\n");
    
              foreach(Car c in arrayOfCars)
                 Console.WriteLine(c.Make + "\t\t" + c.Year);
    
              // Demo ascending sort of numeric value with IComparer.
              Array.Sort(arrayOfCars,Car.SortYearAscending());
              Console.WriteLine("\nArray - Sorted by Year (Ascending - IComparer)\n");
    
              foreach(Car c in arrayOfCars)
                 Console.WriteLine(c.Make + "\t\t" + c.Year);
    
              // Demo descending sort of string value with IComparer.
              Array.Sort(arrayOfCars,Car.SortMakeDescending());
              Console.WriteLine("\nArray - Sorted by Make (Descending - IComparer)\n");
    
              foreach(Car c in arrayOfCars)
                 Console.WriteLine(c.Make + "\t\t" + c.Year);
    
              // Demo descending sort of numeric value using IComparer.
              Array.Sort(arrayOfCars,Car.SortYearDescending());
              Console.WriteLine("\nArray - Sorted by Year (Descending - IComparer)\n");
    
              foreach(Car c in arrayOfCars)
                 Console.WriteLine(c.Make + "\t\t" + c.Year);
    
              Console.ReadLine();
           }
       }
    }
    
  3. Adicione uma classe ao projeto. Nomeie o carro da classe.

  4. Substitua o código no Car.cs pelo seguinte código:

    using System;
    using System.Collections;
    namespace ConsoleEnum
    {
       public class Car : IComparable
       {
          // Beginning of nested classes.
          // Nested class to do ascending sort on year property.
          private class SortYearAscendingHelper: IComparer
          {
             int IComparer.Compare(object a, object b)
             {
                Car c1=(Car)a;
                Car c2=(Car)b;
    
                if (c1.year > c2.year)
                   return 1;
    
                if (c1.year < c2.year)
                   return -1;
    
                else
                   return 0;
             }
          }
    
          // Nested class to do descending sort on year property.
          private class SortYearDescendingHelper: IComparer
          {
             int IComparer.Compare(object a, object b)
             {
                Car c1=(Car)a;
                Car c2=(Car)b;
    
                if (c1.year < c2.year)
                   return 1;
    
                if (c1.year > c2.year)
                   return -1;
    
                else
                   return 0;
             }
          }
    
          // Nested class to do descending sort on make property.
          private class SortMakeDescendingHelper: IComparer
          {
             int IComparer.Compare(object a, object b)
             {
                Car c1=(Car)a;
                Car c2=(Car)b;
                 return String.Compare(c2.make,c1.make);
             }
          }
          // End of nested classes.
          private int year;
          private string make;
    
          public Car(string Make,int Year)
          {
             make=Make;
             year=Year;
          }
    
          public int Year
          {
             get  {return year;}
             set {year=value;}
          }
    
          public string Make
          {
             get {return make;}
             set {make=value;}
          }
          // Implement IComparable CompareTo to provide default sort order.
          int IComparable.CompareTo(object obj)
          {
             Car c=(Car)obj;
             return String.Compare(this.make,c.make);
          }
          // Method to return IComparer object for sort helper.
          public static IComparer SortYearAscending()
          {
             return (IComparer) new SortYearAscendingHelper();
          }
          // Method to return IComparer object for sort helper.
          public static IComparer SortYearDescending()
          {
             return (IComparer) new SortYearDescendingHelper();
          }
          // Method to return IComparer object for sort helper.
          public static IComparer SortMakeDescending()
          {
            return (IComparer) new SortMakeDescendingHelper();
          }
    
       }
    }
    
  5. Execute o projeto. A saída a seguir é exibida na janela Console :

    Array - Unsorted
    
    Ford 1992
    Fiat 1988
    Buick 1932
    Ford 1932
    Dodge 1999
    Honda 1977
    
    Array - Sorted by Make (Ascending - IComparable)
    
    Buick 1932
    Dodge 1999
    Fiat 1988
    Ford 1932
    Ford 1992
    Honda 1977
    
    Array - Sorted by Year (Ascending - IComparer)
    
    Ford 1932
    Buick 1932
    Honda 1977
    Fiat 1988
    Ford 1992
    Dodge 1999
    
    Array - Sorted by Make (Descending - IComparer)
    
    Honda 1977
    Ford 1932
    Ford 1992
    Fiat 1988
    Dodge 1999
    Buick 1932
    
    Array - Sorted by Year (Descending - IComparer)
    
    Dodge 1999
    Ford 1992
    Fiat 1988
    Honda 1977
    Buick 1932
    Ford 1932