次の方法で共有


Visual CSharp で IComparable インターフェイスと IComparer インターフェイスを使用する

この記事では、Visual C# での IComparer インターフェイスと IComparable インターフェイスの使用方法について説明します。

元の製品バージョン: Visual C#
元の KB 番号: 320727

まとめ

IComparableインターフェイスとIComparer インターフェイスについては、2 つの理由から同じ記事で説明します。 これらのインターフェイスは、一緒に頻繁に使用されます。 インターフェイスは似ていますが、名前は似ていますが、さまざまな目的に対応します。

既に IComparerをサポートしている型 (文字列や整数など) の配列がある場合は、 IComparerへの明示的な参照を指定せずに、その配列を並べ替えることができます。 その場合、配列の要素は、 IComparer (Comparer.Default) の既定の実装にキャストされます。 ただし、カスタム オブジェクトの並べ替えまたは比較機能を提供する場合は、これらのインターフェイスのいずれかまたは両方を実装する必要があります。

この記事では、Microsoft .NET Framework クラス ライブラリ名前空間 System.Collectionsを参照します。

IComparable

IComparableの役割は、特定の型の 2 つのオブジェクトを比較する方法を提供することです。 オブジェクトに任意の順序付け機能を提供する場合に必要です。 IComparableは、オブジェクトの既定の並べ替え順序を提供すると考えてください。 たとえば、型のオブジェクトの配列があり、その配列に対して Sort メソッドを呼び出した場合、並べ替え中にオブジェクトの比較 IComparable 提供されます。 IComparable インターフェイスを実装する場合は、次のように CompareTo メソッドを実装する必要があります。

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

メソッドの比較は、比較対象の値のデータ型によって異なります。 String.Compare は、比較のために選択されるプロパティが文字列であるため、この例で使用されます。

IComparer

IComparerの役割は、より多くの比較メカニズムを提供することです。 たとえば、複数のフィールドまたはプロパティ、同じフィールドの昇順と降順、またはその両方にクラスの順序を指定できます。

IComparerの使用は 2 段階のプロセスです。 まず、 IComparerを実装するクラスを宣言してから、 Compare メソッドを実装します。

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

Note

IComparer.Compareメソッドには、3 番目の比較が必要です。 10、または -1 は、一方の値が他方より大きいか、等しいか、またはそれより小さいかに応じて返されます。 並べ替え順序 (昇順または降順) は、このメソッドの論理演算子を切り替えることで変更できます。

2 番目の手順では、 IComparer オブジェクトのインスタンスを返すメソッドを宣言します。

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

この例では、IComparerを受け入れるオーバーロードされたArray.Sort メソッドを呼び出すときに、オブジェクトが 2 番目の引数として使用されます。 IComparerの使用は配列に限定されません。 これは、多くの異なるコレクション クラスとコントロール クラスの引数として受け入れられます。

手順の例

次の例では、これらのインターフェイスの使用方法を示します。 IComparerIComparableを示すために、Carという名前のクラスが作成されます。 Car オブジェクトには、make プロパティと year プロパティがあります。 make フィールドの昇順の並べ替えは、 IComparable インターフェイスを介して有効になり、make フィールドの降順の並べ替えは、 IComparer インターフェイスを介して有効になります。 IComparerを使用して、year プロパティに対して昇順と降順の両方の並べ替えが提供されます。

  1. Visual C# で、新しいコンソール アプリケーション プロジェクトを作成します。 アプリケーションに ConsoleEnum という名前を付けます。

  2. Program.csHost.csとして名前を変更し、コードを次のコードに置き換えます。

    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. プロジェクトにクラスを追加します。 クラスに Car という名前を付けます。

  4. Car.csのコードを次のコードに置き換えます。

    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. プロジェクトを実行します。 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