Usar las IComparable IComparer interfaces y en Visual CSharp

En este artículo se describe el uso de IComparer e IComparable interfaces en Visual C#.

Versión del producto original:   Visual C #
Número KB original:   320727

Resumen

Las IComparable IComparer interfaces y se explican en el mismo artículo por dos motivos. Estas interfaces se usan con frecuencia juntos. Aunque las interfaces son similares y tienen nombres similares, sirven para diferentes propósitos.

Si tiene una matriz de tipos (como cadena o entero) que ya son compatibles, puede ordenar esa matriz sin proporcionar ninguna referencia IComparer explícita a IComparer . En ese caso, los elementos de la matriz se convierten en la implementación predeterminada de IComparer ( Comparer.Default ) por usted. Sin embargo, si desea proporcionar la capacidad de ordenación o comparación para los objetos personalizados, debe implementar cualquiera de estas interfaces o ambas.

En este artículo se hace referencia al espacio de .NET Framework biblioteca de clases de Microsoft System.Collections .

IComparable

El rol de IComparable es proporcionar un método para comparar dos objetos de un tipo determinado. Es necesario si desea proporcionar cualquier funcionalidad de ordenación para el objeto. Piense en IComparable proporcionar un criterio de ordenación predeterminado para los objetos. Por ejemplo, si tiene una matriz de objetos de su tipo y llama al método en esa matriz, proporciona la comparación de objetos Sort IComparable durante la ordenación. Al implementar la IComparable interfaz, debe implementar el CompareTo método de la siguiente manera:

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

La comparación en el método es diferente en función del tipo de datos del valor que se está comparando. String.Compare se usa en este ejemplo porque la propiedad elegida para la comparación es una cadena.

IComparer

El rol de IComparer es proporcionar más mecanismos de comparación. Por ejemplo, es posible que desee proporcionar el orden de la clase en varios campos o propiedades, orden ascendente y descendente en el mismo campo, o ambos.

El IComparer uso es un proceso de dos pasos. En primer lugar, declare una clase que implemente IComparer y, a continuación, implemente el 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;
   }
}

Nota

El IComparer.Compare método requiere una comparación terciaria. Se devuelve 1, 0 o -1 en función de si un valor es mayor que, igual o menor que el otro. El criterio de ordenación (ascendente o descendente) se puede cambiar cambiando los operadores lógicos de este método.

El segundo paso es declarar un método que devuelve una instancia del IComparer objeto:

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

En este ejemplo, el objeto se usa como el segundo argumento cuando se llama al método Array.Sort sobrecargado que acepta IComparer . El uso de IComparer no está limitado a matrices. Se acepta como argumento en muchas clases de control y colección diferentes.

Ejemplo paso a paso

En el ejemplo siguiente se muestra el uso de estas interfaces. Para demostrar IComparer y , se crea una clase IComparable Car denominada. El Car objeto tiene las propiedades make y year. Se habilita una ordenación ascendente para el campo make a través de la interfaz y se habilita una ordenación descendente en el campo make a través IComparable de la IComparer interfaz. Se proporcionan ordenaciones ascendentes y descendentes para la propiedad year mediante IComparer .

  1. En Visual C#, cree un nuevo proyecto de aplicación de consola. Asigne a la aplicación el nombre ConsoleEnum.

  2. Cambie el nombre program.cs como Host.cs y, a continuación, reemplace el código por el siguiente código.

    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. Agregue una clase al proyecto. Asigne un nombre a la clase Car.

  4. Reemplace el código de Car.cs por el siguiente 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. Ejecute el proyecto. La siguiente salida aparece en la ventana Consola:

    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