2012-10-29 13 views
6
नीचे

नमूना कार्यक्रम:क्या आप इस जेनेरिक व्यवहार को समझा सकते हैं और यदि मेरे पास कोई कामकाज है?

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 

namespace GenericsTest 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      IRetrievable<int, User> repo = new FakeRepository(); 

      Console.WriteLine(repo.Retrieve(35)); 
     } 
    } 

    class User 
    { 
     public int Id { get; set; } 
     public string Name { get; set; } 
    } 

    class FakeRepository : BaseRepository<User>, ICreatable<User>, IDeletable<User>, IRetrievable<int, User> 
    { 
     // why do I have to implement this here, instead of letting the 
     // TKey generics implementation in the baseclass handle it? 
     //public User Retrieve(int input) 
     //{ 
     // throw new NotImplementedException(); 
     //} 
    } 

    class BaseRepository<TPoco> where TPoco : class,new() 
    { 
     public virtual TPoco Create() 
     { 
      return new TPoco(); 
     } 

     public virtual bool Delete(TPoco item) 
     { 
      return true; 
     } 

     public virtual TPoco Retrieve<TKey>(TKey input) 
     { 
      return null; 
     } 
    } 

    interface ICreatable<TPoco> { TPoco Create(); } 
    interface IDeletable<TPoco> { bool Delete(TPoco item); } 
    interface IRetrievable<TKey, TPoco> { TPoco Retrieve(TKey input); } 
} 

यह नमूना कार्यक्रम इंटरफेस मेरी वास्तविक कार्यक्रम का उपयोग करता है का प्रतिनिधित्व करता है, और (FakeRepository में बाहर टिप्पणी की) समस्या मैं आ रही हैं दर्शाता है। मैं बेस क्लास द्वारा सामान्य रूप से संभालने के लिए इस विधि कॉल को कॉल करना चाहता हूं (जो कि मेरे वास्तविक उदाहरण में दिए गए मामलों में से 9 5% को संभालने में सक्षम है), जिससे टीके के प्रकार को स्पष्ट रूप से निर्दिष्ट करके बाल कक्षाओं में ओवरराइड की अनुमति मिलती है। यह कोई फर्क नहीं पड़ता कि मैं iretrievable के लिए उपयोग की जाने वाली पैरामीटर बाधाओं का उपयोग करता हूं, मैं बेस क्लास के माध्यम से कभी भी कॉल कॉल नहीं कर सकता।

इसके अलावा, अगर कोई इस तरह के व्यवहार को लागू करने के लिए वैकल्पिक तरीका देख सकता है और परिणाम प्राप्त कर रहा हूं, तो मैं इसे देखकर बहुत दिलचस्पी लेता हूं।

विचार?

उत्तर

3

कि कोड इसी कारण इस सरल उदाहरण के लिए संकलन नहीं है संकलित नहीं करता है:

public interface IBar 
{ 
    void Foo(int i); 
} 

public class Bar : IBar 
{ 
    public void Foo<T>(T i) 
    { 
    } 
} 

विधियों में केवल एक ही हस्ताक्षर नहीं है। हां, आप someBar.Foo(5) पर कॉल कर सकते हैं और यह T से int को हल करेगा, लेकिन तथ्य यह है कि FooBar में अभी भी एक विधि के समान हस्ताक्षर नहीं है जो वास्तव में int पैरामीटर के रूप में लेता है।

आप इस प्रकार में गैर-जेनेरिक और जेनेरिक विधि दोनों के द्वारा इसे और अधिक प्रदर्शित कर सकते हैं; यह एक अस्पष्टता संबंधी त्रुटि में परिणाम नहीं करता है:

public class Bar : IBar 
{ 
    public void Foo(int i) 
    { 

    } 
    public void Foo<T>(T i) 
    { 
    } 
} 

वास्तव में आपकी समस्या को हल करने के लिए के रूप में, आप ऐसा कर सकता है:

class FakeRepository : BaseRepository<User>, ICreatable<User>, IDeletable<User>, IRetrievable<int, User> 
{ 
    public User Retrieve(int input) 
    { 
     return Retrieve<int>(input); 
    } 
} 

इसका मतलब यह होगा FakeRespository है कि दोनों एक सामान्य और गैर सामान्य Retrieve का संस्करण, लेकिन अंत में सभी कॉल अभी भी सामान्य संस्करण के लिए निर्देशित हैं।

1

संकलक पता नहीं क्या TKeyBaseRepository में है और IRetreivable से संबंधित करते का कोई तरीका नहीं है (ध्यान दें कि सामान्य तरीकों गैर सामान्य लोगों के समान हस्ताक्षर नहीं है)।

मुझे लगता है कि आप इन पंक्तियों के साथ कुछ और, इंटरफ़ेस इनहेरीट कर आधार वर्ग के साथ चाहते हैं, और भी TKey निर्दिष्ट करने के लिए:

class FakeRepository : BaseRepository<int, User> 
{ 
} 

class BaseRepository<TKey, TPoco> : ICreatable<TPoco>, IDeletable<TPoco>, IRetrievable<TKey, TPoco> where TPoco : class,new() 
{ 
    public virtual TPoco Create() 
    { 
     return new TPoco(); 
    } 

    public virtual bool Delete(TPoco item) 
    { 
     return true; 
    } 

    public virtual TPoco Retrieve<TKey>(TKey input) 
    { 
     return null; 
    } 
} 
+0

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

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