2011-05-07 16 views
7

मैं एक रणनीति पैटर्न को लागू करने की कोशिश कर रहा हूं ताकि मुझे "खाता" में कुछ "लाभ" लागू करने की अनुमति दी जा सके। नीचे दिए गए कोड में, मैं इंटरफ़ेस की अपेक्षा रखने वाले एक शब्दकोश में इंटरफ़ेस का अपना कार्यान्वयन नहीं जोड़ सकता। मुझे लगता है कि यह contravariance समस्या किसी तरह का है, लेकिन यह है कि मैं ऐसा करने में सक्षम होना चाहिए लगता है:Invariant विरासत समस्या

संपादित करें:
के बाद से जवाब यह है कि यह सिर्फ संभव नहीं है, हो रहा है कि कैसे प्राप्त करने के लिए पर कोई सुझाव क्या मैं यहाँ जा रहा हूँ?

void Main() 
{ 
    var provider = new BenefitStrategyProvider(); 

    var freeBenefit = new FreeBenefit(); 

    var strategy = provider.GetStrategy(freeBenefit); 

    strategy.ApplyBenefit(freeBenefit, new Account()); 

} 

public class BenefitStrategyProvider 
{ 
    private Dictionary<Type, IBenefitStrategy<BenefitBase>> _strategies = new Dictionary<Type, IBenefitStrategy<BenefitBase>>(); 

    public BenefitStrategyProvider() 
    { 
     /* Why can't I add this? */ 
     _strategies.Add(typeof(FreeBenefit), new FreeBenefitStrategy()); 
    } 

    public IBenefitStrategy<BenefitBase> GetStrategy(BenefitBase benefit) 
    { 
     return _strategies[benefit.GetType()]; 
    } 

} 

public class Account {} 

public abstract class BenefitBase 
{ 
    public string BenefitName {get;set;}  
} 

public class FreeBenefit : BenefitBase {} 

public interface IBenefitStrategy<T> where T: BenefitBase 
{ 
    void ApplyBenefit(T benefit, Account account); 
} 

public class FreeBenefitStrategy : IBenefitStrategy<FreeBenefit> 
{ 
    public void ApplyBenefit(FreeBenefit benefit, Account account) 
    { 
     Console.WriteLine("Free Benefit applied"); 
    } 
} 
+0

क्या आप .NET 4 का उपयोग कर रहे हैं? अमान्य विचरण: – Tejs

+0

@Tejs हाँ मैं .net 4.0 – scottm

उत्तर

1

संपादित - स्वरूपण इंजन <angled brackets> में सब कुछ हटा दिया था, जो यह नहीं बल्कि बनाया समझना असंभव है। क्षमा करें अगर यह भ्रमित था!

FreeBenefitStrategyIBenefitStrategy<FreeBenefit> लागू करता है। यह केवल FreeBenefits लागू कर सकता है, किसी अन्य प्रकार का लाभ नहीं। यह IBenefitStrategy<BenefitBase> नहीं है, इसलिए आप इसे उन लोगों के संग्रह में नहीं डाल सकते हैं। तार्किक रूप से, IBenefiteStrategyBenefitBase में contravariant किया जा सकता है, लेकिन यह तुम यहाँ मदद नहीं करता है - एक IBenefitStrategy<BenefitBase> का दावा है, लाभ के सभी प्रकार लागू करने के लिए सक्षम होने के लिए तो एक IBenefitStrategy<BenefitBase> है-एक IBenefitStrategy<FreeBenefit>, लेकिन बातचीत सच नहीं है - एक IBenefitStrategy<FreeBenefit> किसी भी BenefitBase लागू नहीं कर सकते हैं।

मुझे नहीं लगता कि एक हेटरोजेनस संग्रह होने का कोई तरीका है जैसे आप टाइप-कास्टिंग के बिना चाहते हैं। यदि आप इसके बारे में सोचते हैं, तो ऐसी कोई विधि नहीं है जिसे आप IBenefitStrategy<FreeBenefit> और IBenefitStrategy<ExpensiveBenefit> दोनों पर ऑब्जेक्ट से साझा करने के अलावा इनकार कर सकते हैं, इसलिए यह समझ में आता है कि प्रकार ऑब्जेक्ट का एक चर ही एकमात्र चीज है जो या तो इंगित कर सकता है। यदि आप उन्हें एक ही शब्दकोश में रखना चाहते हैं, तो आपको इसे Dictionary<Type, object> बनाना होगा। आप जेनेरिक होने के लिए GetStrategy बदल सकते हैं और उपयुक्त टाइप-कास्टिंग लागू कर सकते हैं, लेकिन अपने शब्दकोश को देखते समय सावधान रहें - सोचें कि क्या होगा यदि ऑब्जेक्ट पास हो गया तो FreeBenefit की उप-श्रेणी है।

1

देखें: Covariance and Contravariance FAQ

How can I create variant generic interfaces and delegates myself? 

The out keyword marks a type parameter as covariant, and the in keyword marks it as contravariant. The two most important rules to remember: 
    You can mark a generic type parameter as covariant if it is used only as a method return type and is not used as a type of formal method parameters. 
    And vice versa, you can mark a type as contravariant if it is used only as a type of formal method parameters and not used as a method return type.
1

आप अपने इंटरफेस के लिए टी बाहर जोड़ने की जरूरत:

public interface IBenefitStrategy<in T> 
+0

कि अंत के ऊपर मुझे इस त्रुटि दे रही है का उपयोग कर रहा प्रकार पैरामीटर 'टी' पर 'IBenefitStrategy .ApplyBenefit (टी, UserQuery.Account)' contravariantly मान्य होना चाहिए। 'टी' कॉन्वर्सेंट है। – scottm

+0

ऐसा इसलिए है क्योंकि यह 'टी में' होना चाहिए, टी 'नहीं'। 'टी' यहां एक प्रकार परिवर्तनीय है, और आपका इंटरफ़ेस केवल 'टी' प्रकार की वस्तुओं को" लेता है "और कभी भी" आउटपुट "नहीं करता है, इसलिए यह contravariance के लिए एक आदर्श नागरिक है। –

+0

@ पॉल जेड, लेकिन जब मैं इसे टी में बना देता हूं, तो मैं कार्यान्वयन नहीं जोड़ सकता! – scottm

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