Utiliser les IComparable interfaces et IComparer dans Visual CSharp

Cet article décrit l’utilisation des IComparer interfaces et IComparable dans Visual C#.

Version d’origine du produit : Visual C#
Numéro de la base de connaissances d’origine : 320727

Résumé

Les IComparable interfaces et IComparer sont abordées dans le même article pour deux raisons. Ces interfaces sont fréquemment utilisées ensemble. Bien que les interfaces soient similaires et aient des noms similaires, elles ont des objectifs différents.

Si vous avez un tableau de types (comme chaîne ou entier) qui prend déjà en charge IComparer, vous pouvez trier ce tableau sans fournir de référence explicite à IComparer. Dans ce cas, les éléments du tableau sont convertis en implémentation par défaut de IComparer (Comparer.Default) pour vous. Toutefois, si vous souhaitez fournir une fonctionnalité de tri ou de comparaison pour vos objets personnalisés, vous devez implémenter l’une de ces interfaces ou les deux.

Cet article fait référence à l’espace de noms System.Collectionsbibliothèque de classes Microsoft .NET Framework .

IComparable

Le rôle de est de IComparable fournir une méthode de comparaison de deux objets d’un type particulier. Cela est nécessaire si vous souhaitez fournir une fonctionnalité de classement pour votre objet. Pensez à fournir un ordre de IComparable tri par défaut pour vos objets. Par exemple, si vous avez un tableau d’objets de votre type et que vous appelez la Sort méthode sur ce tableau, IComparable fournit la comparaison des objets pendant le tri. Lorsque vous implémentez l’interface IComparable , vous devez implémenter la CompareTo méthode, comme suit :

// 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 comparaison dans la méthode est différente en fonction du type de données de la valeur qui est comparée. String.Compare est utilisé dans cet exemple, car la propriété choisie pour la comparaison est une chaîne.

IComparer

Le rôle de est de fournir davantage de IComparer mécanismes de comparaison. Par exemple, vous pouvez indiquer l’ordre de votre classe sur plusieurs champs ou propriétés, l’ordre croissant et décroissant sur le même champ, ou les deux.

L’utilisation IComparer est un processus en deux étapes. Tout d’abord, déclarez une classe qui implémente IComparer, puis implémentez la Compare méthode :

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;
   }
}

Remarque

La IComparer.Compare méthode nécessite une comparaison tertiaire. 1, 0 ou -1 est retourné selon qu’une valeur est supérieure, égale ou inférieure à l’autre. L’ordre de tri (croissant ou décroissant) peut être modifié en basculant les opérateurs logiques dans cette méthode.

La deuxième étape consiste à déclarer une méthode qui retourne une instance de votre IComparer objet :

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

Dans cet exemple, l’objet est utilisé comme deuxième argument lorsque vous appelez la méthode surchargée Array.Sort qui accepte IComparer. L’utilisation de IComparer n’est pas limitée aux tableaux. Il est accepté comme argument dans de nombreuses classes de contrôle et de collection différentes.

Exemple pas à pas

L’exemple suivant illustre l’utilisation de ces interfaces. Pour illustrer IComparer et IComparable, une classe nommée Car est créée. L’objet Car a les propriétés make et year. Un tri croissant pour le champ make est activé via l’interface IComparable , et un tri décroissant sur le champ make est activé via l’interface IComparer . Les tris croissant et décroissant sont fournis pour la propriété year à l’aide IComparerde .

  1. Dans Visual C#, créez un projet Application console. Nommez l’application ConsoleEnum.

  2. Renommez Program.csen tant que Host.cs, puis remplacez le code par le code suivant.

    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. Ajoutez une classe au projet. Nommez la classe Car.

  4. Remplacez le code dans Car.cs par le code suivant :

    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. Exécutez le projet. La sortie suivante s’affiche dans la fenêtre 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