程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> C# >> 關於C# >> 泛型--實現IComparable接口

泛型--實現IComparable接口

編輯:關於C#

9.6.1 實現IComparable接口

像所有集合類一樣,List實現了Sort()方法,它允許您對所有實現了IComparable接口的對象進行排序。在下一個例子中,您將修改Employee類以實現IComparable:

public class Employee : IComparable<Employee>

實現IComparable<Employee>接口,Employee對象必須提供CompareTo()方法:

public int CompareTo(Employee rhs)
{
  return this.empID.CompareTo(rhs.empID);
}

CompareTo()方法把Employee做為參數。我們知道使用Employee是因為這是一個類型安全的集合。當前Employee對象必須把它自己跟做為參數傳遞進來的Employee進行對比,如果返回-1,表示它小於參數,如果大於參數則返回1,如果兩者相等則返回0。這意味著決定大於、小於、等於的是Employee。在本例中,您委托成員empId進行比較。empId成員是一個int類型,並使用了整數類型默認的CompareTo()方法,以對比兩個值之間的大小。

System.Int32類實現了Icomparable<Int32>接口,所以您可以把比較的職責委托給整數類型。

您現在准備對員工數組列表(empList)進行排序,為了查看排序是否正常工作,您需要隨機地添加整數和Employee實例到它們各自的數組中。創建隨機數,需要實例化Random類;調用Random對象的Next()方法產生隨機數。Next()方法是一個重載方法;一種版本允許您傳遞一個整數值,表示您想要的最大隨機數。在本例中,您將傳遞10來產生一個0到10之間的隨機數:(譯者注:參數為10,最大的隨機數只能為9)

Random r = new Random();

r.Next(10);

例9-14創建了一個整型數組和一個Employee數組,並給兩者填充隨機數,並打印它們的值。隨後排序數組並打印新值。

例9-14 排序整數和employee數組

using System;
using System.Collections.Generic;
using System.Text;
namespace IComparable
{
  // 一個簡單的用於存儲在數組中的類
  public class Employee : IComparable<Employee>
  {
   private int empID;
   public Employee( int empID )
   {
     this.empID = empID;
   }
   public override string ToString( )
   {
     return empID.ToString( );
   }
   public bool Equals( Employee other )
   {
     if ( this.empID == other.empID )
     {
      return true;
     }
     else
     {
      return false;
     }
   }
   // Employee使用整數默認的CompareTo方法
   public int CompareTo( Employee rhs )
   {
     return this.empID.CompareTo( rhs.empID );
   }
  }
  public class Tester
  {
   static void Main( )
   {
     List<Employee> empArray = new List<Employee>( );
     List<Int32> intArray = new List<Int32>( );
     // 產生整數和employee的ID的隨機數
     Random r = new Random( );
     // 填充數組
     for ( int i = 0; i < 5; i++ )
     {
      // 添加隨機的employee的id
      empArray.Add( new Employee( r.Next( 10 ) + 100 ) );
      // 添加隨機的整數
      intArray.Add( r.Next( 10 ) );
     }
     // 顯示整型數組中的所有內容
     for ( int i = 0; i < intArray.Count; i++ )
     {
      Console.Write( "{0} ", intArray[i].ToString( ) );
     }
     Console.WriteLine( "\n" );
     // 顯示Employee數組中的所有內容
     for ( int i = 0; i < empArray.Count; i++ )
     {
      Console.Write( "{0} ", empArray[i].ToString( ) );
     }
     Console.WriteLine( "\n" );
     // 整型數組排序
     intArray.Sort( );
     for ( int i = 0; i < intArray.Count; i++ )
     {
      Console.Write( "{0} ", intArray[i].ToString( ) );
     }
     Console.WriteLine( "\n" );
     // employee數組排序並顯示
     //原文的下面這兩句應該注釋掉,現在還沒用到
     //Employee.EmployeeComparer c = Employee.GetComparer( );
     //empArray.Sort(c);
     empArray.Sort( );
     // 顯示Employee數組中的所有內容
     for ( int i = 0; i < empArray.Count; i++ )
     {
      Console.Write( "{0} ", empArray[i].ToString( ) );
     }
     Console.WriteLine( "\n" );
   }
  }
}

輸出結果:

4 5 6 5 7
108 100 101 103 103
4 5 5 6 7
100 101 103 103 108

輸出顯示整型數組和Employee數組產生的是隨機數。排序後,顯示的是已經進行排序後的值。

9.6.2 實現IComparer接口

當您在List中調用Sort(),默認的IComparer(譯者注:這裡可能是錯誤,應該為IComparable)實現被調用,它調用IComparable所實現的CompareTo()方法對List內的每個元素進行快速排序。

當您想控制排列方式時,可以自由地創建自己的IComparer實現。在下一個例子中,將在Employee中添加第二個字段:yearsOfSvc。您希望在List中按兩種字段empID或yearsOfSvc來對Employee對象進行排序。

為了達到這個目的,需要創建IComparer的實現,用於傳遞給List中Sort()方法的參數。這個IComparer類是EmployeeComparer,它讓Employee對象知道如何進行排序。

EmployeeComparer類有一個WhichComparison屬性,它是Employee. EmployeeComparer.ComparisonType類型:

public Employee.EmployeeComparer.ComparisonType WhichComparison
{
  get{return whichComparison;}
  set{whichComparison = value;}
}

ComparisonType是一個枚舉類型,它有兩個值:empID或yearsOfSvc(指示您希望按員工ID還是工齡進行排序):

public enum ComparisonType
{
  EmpID,
  YearsOfService
};

在調用Sort()方法之前,創建EmployeeComparer的實例並設置它的ComparisonType屬性:

Employee.EmployeeComparer c = Employee.GetComparer();

c.WhichComparison=Employee.EmployeeComparer.ComparisonType.EmpID;

empArray.Sort(c);

調用Sort()方法之時,List會調用EmployeeComparer中的Compare方法,並把當前要對比的字段通過WhickComparison屬性傳遞給Employee.CompareTo()方法:

public int Compare( Employee lhs, Employee rhs )
{
  return lhs.CompareTo( rhs, WhichComparison );
}

Employee對象必須實現一個自定義的CompareTo()方法,用於獲得比較方式並按照要求進行對比:

public int CompareTo(Employee rhs,
  Employee.EmployeeComparer.ComparisonType which)
{
  switch (which)
  {
   case Employee.EmployeeComparer.ComparisonType.EmpID:
     return this.empID.CompareTo(rhs.empID);
   case Employee.EmployeeComparer.ComparisonType.Yrs:
     return this.yearsOfSvc.CompareTo(rhs.yearsOfSvc);
  }
  return 0;
}

例9-15是這個例子的完整代碼。為了簡化例子,整型數組已經被移除,用於輸出的Employee的ToString()方法也增加了代碼以讓您看得到排序的效果。

例9-15 按員工的ID和工齡進行排序

using System;
using System.Collections.Generic;
using System.Text;
namespace IComparer
{
  public class Employee : IComparable<Employee>
  {
    private int empID;
    private int yearsOfSvc = 1;
    public Employee(int empID)
    {
      this.empID = empID;
    }
    public Employee(int empID, int yearsOfSvc)
    {
      this.empID = empID;
      this.yearsOfSvc = yearsOfSvc;
    }
    public override string ToString()
    {
      return "ID:" + empID.ToString() +
        ". Years of Svc:" + yearsOfSvc.ToString();
    }
    public bool Equals(Employee other)
    {
      if (this.empID == other.empID)
      {
        return true;
      }
      else
      {
        return false;
      }
    }
    //靜態方法,用於獲取一個Comparer對象
    public static EmployeeComparer GetComparer()
    {
      return new Employee.EmployeeComparer();
    }
    public int CompareTo(Employee rhs)
    {
      return this.empID.CompareTo(rhs.empID);
    }
    //通過自定義comparer來調用指定的實現
    public int CompareTo(Employee rhs,
      Employee.EmployeeComparer.ComparisonType which)
    {
      switch (which)
      {
        case Employee.EmployeeComparer.ComparisonType.EmpID:
          return this.empID.CompareTo(rhs.empID);
        case Employee.EmployeeComparer.ComparisonType.Yrs:
          return this.yearsOfSvc.CompareTo(rhs.yearsOfSvc);
      }
      return 0;
    }
    //實現IComparer接口的嵌套類
    public class EmployeeComparer : IComparer<Employee>
    {
      private Employee.EmployeeComparer.ComparisonType
        whichComparison;
      //比較方式枚舉
      public enum ComparisonType
      {
        EmpID,
        Yrs
      };
      public bool Equals(Employee lhs, Employee rhs)
      {
        return this.Compare(lhs, rhs) == 0;
      }
      public int GetHashCode(Employee e)
      {
        return e.GetHashCode();
      }
      public int Compare(Employee lhs, Employee rhs)
      {
        return lhs.CompareTo(rhs, WhichComparison);
      }
      public Employee.EmployeeComparer.ComparisonType
        WhichComparison
      {
        get { return whichComparison; }
        set { whichComparison = value; }
      }
    }
  }
  public class Tester
  {
    static void Main()
    {
      List<Employee> empArray = new List<Employee>();
      Random r = new Random();
      for (int i = 0; i < 5; i++)
      {
        //添加一個隨機的員工ID
        empArray.Add(new Employee(
          r.Next(10) + 100, r.Next(20)));
      }
      //顯示Employee數組的所有內容
      for (int i = 0; i < empArray.Count; i++)
      {
        Console.Write("\n{0} ", empArray[i].ToString());
      }
      Console.WriteLine("\n");
      //排序並顯示Employee數組
      Employee.EmployeeComparer c = Employee.GetComparer();
      c.WhichComparison =
        Employee.EmployeeComparer.ComparisonType.EmpID;
      empArray.Sort(c);
      //顯示Employee數組的所有內容
      for (int i = 0; i < empArray.Count; i++)
      {
        Console.Write("\n{0} ", empArray[i].ToString());
      }
      Console.WriteLine("\n");
      c.WhichComparison = Employee.EmployeeComparer.ComparisonType.Yrs;
      empArray.Sort(c);
      for (int i = 0; i < empArray.Count; i++)
      {
        Console.Write("\n{0} ", empArray[i].ToString());
      }
      Console.WriteLine("\n");
    }
  }
}

輸出結果:

ID: 103. Years of Svc: 11
ID: 108. Years of Svc: 15
ID: 107. Years of Svc: 14
ID: 108. Years of Svc: 5
ID: 102. Years of Svc: 0

ID: 102. Years of Svc: 0
ID: 103. Years of Svc: 11
ID: 107. Years of Svc: 14
ID: 108. Years of Svc: 15
ID: 108. Years of Svc: 5

ID: 102. Years of Svc: 0
ID: 108. Years of Svc: 5
ID: 103. Years of Svc: 11
ID: 107. Years of Svc: 14
ID: 108. Years of Svc: 15

第一塊輸出顯示的是Employee對象被加進List時的情形。員工ID值和工齡是隨機順序的。第二塊顯示的是按員工ID排序後的結果,第三塊顯示的是按工齡排序後的結果。

如果您如例9-11那樣創建自己的集合,並希望實現IComparer,可能需要確保所有放在列表中的類型都實現了IComparer接口(這樣他們才有可能被排序),這可以通過前面講述的約束來實現。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved