2010-01-09 5 views
7

(सी #, वीएस -2008) एक कार्यक्रम में मैं काम कर रहा हूं, मेरे पास बहुत सारी ऑब्जेक्ट्स हैं जिनके पास सभी आईडी हैं और आईसीओपरपेबल लागू करें ताकि विभिन्न ऑब्जेक्ट्स की सूची आईडी द्वारा आसानी से खोजी जा सके। जब से मैं प्रतिलिपि करने/चिपकाने कोड नफरत है, मैंने सोचा कि मैं एक आधार वर्ग के लिए नीचे सार चाहते कार्यक्षमता की कि बिट, इसलिए जैसे:एक सार बेस क्लास 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() और मैं सीधे यह लागू करने की उम्मीद कर रहा था कि आईडीओब्जेक्ट से प्राप्त प्रत्येक वर्ग केवल सटीक उसी वर्ग के अन्य लोगों के लिए तुलनात्मक है। तो मुझे लगता है कि कैसे करना है यह पता लगाने की उम्मीद कर रही थी और इस

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

मुझे लगता है कि व्युत्पन्न कक्षा के प्रकार समान हैं, यह सुनिश्चित करने के मुकाबले आपको बड़ी समस्याएं हैं। आप अद्वितीय आईडी उत्पन्न करने की ज़िम्मेदारी के साथ व्युत्पन्न वर्ग को भी परेशान कर रहे हैं। इसके लिए व्युत्पन्न कक्षा को यह पता होना चाहिए कि पहले अन्य आईडी क्या आवंटित की गई थीं। वास्तव में, इसके लिए एक वर्ग कारखाने की आवश्यकता होती है। आपको अपने अमूर्त वर्ग के संरक्षक को संरक्षित करके इसे लागू करने की आवश्यकता होगी।

बहुत व्यावहारिक नहीं है। यदि आईडी केवल एक अपारदर्शी संख्या है जो ऑब्जेक्ट पहचान स्थापित करती है तो आईडी को स्वयं निर्दिष्ट करने पर विचार करें। अंतिम असाइन किए गए ट्रैक का ट्रैक रखने के लिए एक स्थिर सदस्य का उपयोग करें। अब यह आसान हो गया है, और आपको अब व्युत्पन्न कक्षा के प्रकारों के बारे में चिंता करने की ज़रूरत नहीं है।

+0

+1। अच्छी बात। मैंने आईडी मुद्दे से बाहर रहते हुए पैटर्न दिखाने के लिए अपना जवाब अपडेट कर दिया है। –

+0

आईडी एक SQLite डीबी इंटीजर प्राथमिक कुंजी कॉलम से आती है - इसलिए वे SQLite द्वारा किसी ऑब्जेक्ट प्रकार के बीच अद्वितीय होने की गारंटी देते हैं, लेकिन विभिन्न प्रकार की दो वस्तुएं अनुमानित रूप से ओवरलैप हो सकती हैं, इसलिए आईसीओपरपेबल को केवल उसी वर्ग के सदस्यों को सीमित करना चाहते हैं। – Drogo

संबंधित मुद्दे