2010-01-09 15 views
7

(C#,VS2008)在我正在研究的一個程序中,我有很多對象都有一個ID並實現了IComparable,因此各個對象的列表很容易通過ID進行搜索。因爲我討厭複製/粘貼代碼,我想我會抽象的功能,位下降到一個基類,像這樣:如何使抽象基類IComparable不比較兩個單獨的繼承類?

using System; 

namespace MyProg.Logic 
{ 
    abstract class IDObject : IComparable<IDObject> 
    { 
     private int miID; 

     public int ID 
     { 
      get { return miID; } 
      set { miID = value; } 
     } 

     public IDObject(int ID) 
     { 
      miID = ID; 
     } 

     #region IComparable<IDObject> Members 

     int IComparable<IDObject>.CompareTo(IDObject other) 
     { 
      return miID.CompareTo(other.miID); 
     } 

     #endregion 
    } 
} 

我看到到的缺點是兩個獨立的類,每個繼承它會可以直接使用.CompareTo()進行比較,我希望強制從IDObject繼承的每個類只能與完全相同類的其他類進行比較。所以,我希望能弄清楚如何做到這一點,與此

using System; 

namespace MyProg.Logic 
{ 
    abstract class IDObject : IComparable<T> where T : IDObject 
    { 
     private int miID; 

     public int ID 
     { 
      get { return miID; } 
      set { miID = value; } 
     } 

     public IDObject(int ID) 
     { 
      miID = ID; 
     } 

     #region IComparable<T> Members 

     int IComparable<T>.CompareTo(T other) 
     { 
      return miID.CompareTo(other.miID); 
     } 

     #endregion 
    } 
} 

出來了,但給出的「約束不允許非通用聲明」

看着它,我編譯錯誤確定有辦法做這樣的事情,以便每個類只能與同一類的其他實例相比,但我無法梳理出語法。

回答

12

您可以使用Curiously Recurring Template Pattern來解決此問題。

abstract class Base<T> : IComparable<T> where T : Base<T> { 
    public int Rank { get; set; } // Order instances of derived type T by Rank 
    public int CompareTo(T other) { return Rank.CompareTo(other.Rank); } 
} 
class Foo : Base<Foo> {} 
class Bar : Base<Bar> {} 

static class Program { 
    static void Main() { 
     var foo1 = new Foo { Rank = 1 }; 
     var foo2 = new Foo { Rank = 2 }; 
     var bar1 = new Bar { Rank = 1 }; 
     var bar2 = new Bar { Rank = 2 }; 

     Console.WriteLine(foo1.CompareTo(foo2)); 
     Console.WriteLine(bar2.CompareTo(bar1)); 

     //error CS1503: Argument '1': cannot convert from 'Bar' to 'Foo' 
     //Console.WriteLine(foo1.CompareTo(bar1)); 
    } 
} 
2

我想你的問題不僅僅是確保派生類的類型相同。您還負責派生類生成唯一 ID。這要求派生類知道以前分配了其他ID。實際上,這需要一個班級工廠。您需要通過使您的抽象類的構造函數受到保護來強制執行該操作。

不太實際。如果ID只是建立對象身份的不透明數字,那麼請考慮自己分配ID。使用靜態成員來跟蹤最後指定的一個。現在它變得簡單了,你不必擔心派生類的類型了。

+0

+1。好點子。我已經更新了我的答案,以顯示該模式,同時避開ID問題。 – 2010-01-09 15:40:15

+0

該ID來自SQLite數據庫整數主鍵列 - 所以他們保證SQLite在對象類型中是唯一的,但兩個不同類型的對象可能會重疊,因此希望將IComparable限制爲只有同一類的成員。 – Drogo 2010-01-09 21:55:54