IStructuralComparable 接口

定义

支持集合对象的结构化比较。

public interface class IStructuralComparable
public interface IStructuralComparable
type IStructuralComparable = interface
Public Interface IStructuralComparable
派生

示例

以下示例创建对象数组 Tuple<T1,T2,T3,T4,T5,T6> ,其中包含 1960 年到 2000 年三个美国城市的人口数据。 性别的第一部分是城市名称。 其余五个组成部分代表从1960年到2000年每隔十年一次的人口。

PopulationComparer 提供了一个 IComparer 实现,该实现允许按其任何一个组件对性元素数组进行排序。 在类的构造函数中向 PopulationComparer 类提供两个值:定义排序顺序的组件的位置,以及指示元组对象应按升序还是降序排序的布尔值。

然后,该示例按未排序的顺序显示数组中的元素,按 1970) 总体 (第三个分量对其进行排序并显示它们,然后按 2000) 总体 (第六个分量排序并显示它们。 请注意,该示例不直接调用 CompareTo 方法。 方法由 Sort(Array, IComparer) 数组中的每个元组对象的 方法隐式调用。

using System;
using System.Collections;
using System.Collections.Generic;

public class PopulationComparer<T1, T2, T3, T4, T5, T6> : IComparer
{
   private int itemPosition;
   private int multiplier = -1;

   public PopulationComparer(int component) : this(component, true)
   { }

   public PopulationComparer(int component, bool descending)
   {
      if (! descending) multiplier = 1;

      if (component <= 0 || component > 6)
         throw new ArgumentException("The component argument is out of range.");

      itemPosition = component;
   }

   public int Compare(object x, object y)
   {
      var tX = x as Tuple<T1, T2, T3, T4, T5, T6>;
      if (tX == null)
      {
         return 0;
      }
      else
      {
         var tY = y as Tuple<T1, T2, T3, T4, T5, T6>;
         switch (itemPosition)
         {
            case 1:
               return Comparer<T1>.Default.Compare(tX.Item1, tY.Item1) * multiplier;
            case 2:
               return Comparer<T2>.Default.Compare(tX.Item2, tY.Item2) * multiplier;
            case 3:
               return Comparer<T3>.Default.Compare(tX.Item3, tY.Item3) * multiplier;
            case 4:
               return Comparer<T4>.Default.Compare(tX.Item4, tY.Item4) * multiplier;
            case 5:
               return Comparer<T5>.Default.Compare(tX.Item5, tY.Item5) * multiplier;
            case 6:
               return Comparer<T6>.Default.Compare(tX.Item6, tY.Item6) * multiplier;
            default:
               return Comparer<T1>.Default.Compare(tX.Item1, tY.Item1) * multiplier;
         }
      }
   }
}

public class Example
{
   public static void Main()
   {
      // Create array of sextuple with population data for three U.S.
      // cities, 1960-2000.
      Tuple<string, int, int, int, int, int>[] cities =
           { Tuple.Create("Los Angeles", 2479015, 2816061, 2966850, 3485398, 3694820),
             Tuple.Create("New York", 7781984, 7894862, 7071639, 7322564, 8008278),
             Tuple.Create("Chicago", 3550904, 3366957, 3005072, 2783726, 2896016) };

      // Display array in unsorted order.
      Console.WriteLine("In unsorted order:");
      foreach (var city in cities)
         Console.WriteLine(city.ToString());
      Console.WriteLine();

      Array.Sort(cities, new PopulationComparer<string, int, int, int, int, int>(3));

      // Display array in sorted order.
      Console.WriteLine("Sorted by population in 1970:");
      foreach (var city in cities)
         Console.WriteLine(city.ToString());
      Console.WriteLine();

      Array.Sort(cities, new PopulationComparer<string, int, int, int, int, int>(6));

      // Display array in sorted order.
      Console.WriteLine("Sorted by population in 2000:");
      foreach (var city in cities)
         Console.WriteLine(city.ToString());
   }
}
// The example displays the following output:
//    In unsorted order:
//    (Los Angeles, 2479015, 2816061, 2966850, 3485398, 3694820)
//    (New York, 7781984, 7894862, 7071639, 7322564, 8008278)
//    (Chicago, 3550904, 3366957, 3005072, 2783726, 2896016)
//    
//    Sorted by population in 1970:
//    (New York, 7781984, 7894862, 7071639, 7322564, 8008278)
//    (Chicago, 3550904, 3366957, 3005072, 2783726, 2896016)
//    (Los Angeles, 2479015, 2816061, 2966850, 3485398, 3694820)
//    
//    Sorted by population in 2000:
//    (New York, 7781984, 7894862, 7071639, 7322564, 8008278)
//    (Los Angeles, 2479015, 2816061, 2966850, 3485398, 3694820)
//    (Chicago, 3550904, 3366957, 3005072, 2783726, 2896016)
Imports System.Collections
Imports System.Collections.Generic

Public Class PopulationComparer(Of T1, T2, T3, T4, T5, T6) : Implements IComparer
   Private itemPosition As Integer
   Private multiplier As Integer = -1
      
   Public Sub New(component As Integer)
      Me.New(component, True)
   End Sub
   
   Public Sub New(component As Integer, descending As Boolean)
      If Not descending Then multiplier = 1
      
      If component <= 0 Or component > 6 Then 
         Throw New ArgumentException("The component argument is out of range.")
      End If
      itemPosition = component
   End Sub 
   
   Public Function Compare(x As Object, y As Object) As Integer _
                   Implements IComparer.Compare
 
      Dim tX = TryCast(x, Tuple(Of T1, T2, T3, T4, T5, T6))
      If tX Is Nothing Then
         Return 0
      Else
         Dim tY = DirectCast(y, Tuple(Of T1, T2, T3, T4, T5, T6))
         Select Case itemPosition
            Case 1
               Return Comparer(Of T1).Default.Compare(tX.Item1, tY.Item1) * multiplier
            Case 2
               Return Comparer(Of T2).Default.Compare(tX.Item2, tY.Item2) * multiplier
            Case 3
               Return Comparer(Of T3).Default.Compare(tX.Item3, tY.Item3) * multiplier
            Case 4
               Return Comparer(Of T4).Default.Compare(tX.Item4, tY.Item4) * multiplier
            Case 5
               Return Comparer(Of T5).Default.Compare(tX.Item5, tY.Item5) * multiplier
            Case 6
               Return Comparer(Of T6).Default.Compare(tX.Item6, tY.Item6) * multiplier
            ' This should never happen.
            Case Else
               Return 0
         End Select      
      End If
   End Function
End Class

Module Example
   Public Sub Main()
      ' Create array of sextuple with population data for three U.S. 
      ' cities, 1960-2000.
      Dim cities() = 
          { Tuple.Create("Los Angeles", 2479015, 2816061, 2966850, 3485398, 3694820),
            Tuple.Create("New York", 7781984, 7894862, 7071639, 7322564, 8008278),  
            Tuple.Create("Chicago", 3550904, 3366957, 3005072, 2783726, 2896016) } 
      
      ' Display array in unsorted order.
      Console.WriteLine("In unsorted order:")
      For Each city In cities
         Console.WriteLine(city.ToString())
      Next
      Console.WriteLine()
      
      Array.Sort(cities, New PopulationComparer(Of String, Integer, Integer, Integer, Integer, Integer)(3)) 
                           
      ' Display array in sorted order.
      Console.WriteLine("Sorted by population in 1970:")
      For Each city In cities
         Console.WriteLine(city.ToString())
      Next
      Console.WriteLine()
      
      Array.Sort(cities, New PopulationComparer(Of String, Integer, Integer, Integer, Integer, Integer)(6))
                           
      ' Display array in sorted order.
      Console.WriteLine("Sorted by population in 2000:")
      For Each city In cities
         Console.WriteLine(city.ToString())
      Next
   End Sub
End Module
' The example displays the following output:
'    In unsorted order:
'    (Los Angeles, 2479015, 2816061, 2966850, 3485398, 3694820)
'    (New York, 7781984, 7894862, 7071639, 7322564, 8008278)
'    (Chicago, 3550904, 3366957, 3005072, 2783726, 2896016)
'    
'    Sorted by population in 1970:
'    (New York, 7781984, 7894862, 7071639, 7322564, 8008278)
'    (Chicago, 3550904, 3366957, 3005072, 2783726, 2896016)
'    (Los Angeles, 2479015, 2816061, 2966850, 3485398, 3694820)
'    
'    Sorted by population in 2000:
'    (New York, 7781984, 7894862, 7071639, 7322564, 8008278)
'    (Los Angeles, 2479015, 2816061, 2966850, 3485398, 3694820)
'    (Chicago, 3550904, 3366957, 3005072, 2783726, 2896016)

注解

使用 IStructuralComparable 接口可以为集合成员实现自定义比较。 也就是说,可以精确定义一个集合对象在排序顺序中与第二个集合对象位于同一位置之前、之后或位于同一位置的含义。 然后,可以指定将此定义与接受 接口的 IStructuralComparable 集合类型一起使用。

接口具有单个成员 ,该成员 CompareTo确定当前集合对象在排序顺序中是小于、等于还是大于第二个对象。 当前实例中的成员或元素与第二个对象中的成员或元素的实际比较由 IComparer 接口实现执行,该实现包含自定义比较的定义。

注意

接口 IStructuralComparable 仅支持排序或排序的结构比较。 接口 IStructuralEquatable 支持结构相等性的自定义比较。

.NET Framework提供两个默认比较器。 一个由 StructuralComparisons.StructuralComparer 属性返回;另一个由 Comparer<T>.Default 属性返回。

泛型元组类 (Tuple<T1>Tuple<T1,T2>Tuple<T1,T2,T3>等) 并且 Array 类提供 接口的 IStructuralComparable 显式实现。 通过在 C#) 中强制转换 (,或在 Visual Basic 中将 () 数组或元组的当前实例转换为IStructuralComparable接口值,并将实现作为方法的参数CompareTo提供IComparer,可以定义数组或集合的自定义排序顺序。 但是,在大多数情况下,不会直接调用 CompareTo 方法。 相反, CompareTo 方法是通过排序方法(如 Sort(Array, IComparer))调用的。 在这种情况下,定义 IComparer 实现并将其作为参数传递给排序方法或集合对象的类构造函数。 然后, CompareTo 每当对集合进行排序时,都会自动调用具有自定义比较器的方法。

方法

CompareTo(Object, IComparer)

确定当前集合对象在排序顺序中的位置是位于另一个对象之前、之后还是与其位置相同。

适用于

另请参阅