2009-12-08 13 views
6

क्यों इस काम:इंटरफेस की सूची बनाम व्युत्पन्न प्रकार की सूची - एक्सप्रेशन प्रकार लौटने के लिए परिवर्तित नहीं कर सकते

public IList<ICoupon> GetCouponsForSite(string siteSlug) 
{ 
    var coupons = _db.Coupons.Where(x => x.Site.slug == siteSlug) 
        .Select(x => new Coupon(x.id)); 

    var list = new List<ICoupon>(); 
    foreach (var coupon in coupons) 
    { 
     list.Add(coupon); 
    } 

    return list; 
} 

लेकिन यह काम नहीं करता है (त्रुटि - प्रकार वापस जाने के लिए अभिव्यक्ति प्रकार परिवर्तित नहीं कर सकते):

public IList<ICoupon> GetCouponsForSite(string siteSlug) 
{ 
    return _db.Coupons.Where(x => x.Site.slug == siteSlug) 
         .Select(x => new Coupon(x.id)).ToList(); 
} 

उत्तर

10

क्योंकि db.Coupons ... ToList() IList<ICoupon> की बजाय IList<Coupon> देता है। IList<Coupon>IList<ICoupon> से प्राप्त नहीं हुआ है क्योंकि सी # 3 जेनेरिक भिन्नता का समर्थन नहीं करता है। (सी # 4 जेनेरिक भिन्नता का समर्थन करता है, लेकिन यह अभी भी इस मामले में नहीं मिलेगा। इस बात पर विचार करें कि जो कोई भी IList<ICoupon> प्राप्त करता है, उसमें कुछ एविइल टाइप टाइप इंपलमेंट्स को अपनाने का प्रयास कर सकता है। लेकिन IList<Coupon> इसे स्वीकार नहीं कर सका क्योंकि कुछ ऐविल टाइप टाइप इंपलमेंटिकूपन कूपन से नहीं निकलता है । एक अलग संदर्भ में यद्यपि यह परिवर्तनीयता मुद्दे की चर्चा के लिए http://hestia.typepad.com/flatlander/2008/12/c-covariance-and-contravariance-by-example.html देखें, और एरिक Lippert लेख वहाँ से जुड़े।)

(आपका पहला टुकड़ा, इसके विपरीत, स्पष्ट रूप से एक List<ICoupon> निर्माण करती है, जो कुछ भी शामिल कर सकते हैं कि ICoupon लागू करता है, और उसके बाद कुछ कूपन ऑब्जेक्ट्स को उस सूची में रखता है। अब अगर रिसीवर कुछ एविल टाइप टाइप इंपलमेंट्स को पोक करने का फैसला करता है, तो सब ठीक है, क्योंकि सूची किसी भी आईसीओपॉन को पकड़ने के लिए बनाई गई थी ही नहीं, वास्तविक कूपन वस्तुओं।)

0

IQueryable<ICoupon>IList<ICoupon> से प्राप्त नहीं है।

+0

एक .ToList() वहाँ में ... – Martin

+0

क्षमा करें, कि नहीं देखा नहीं है। वापसी कथन 'var x = _db ...;' फिर 'वापसी x' करें। यह देखने के लिए 'var x' पर होवर करें कि वीएस किस प्रकार सोचता है। –

+0

अभिव्यक्ति प्रकार सूची को वापस लौटने के लिए नहीं बदल सकता है ILI Martin

4

यह परोक्ष सूची <ICoupon> सूची में < कूपन > डाली नहीं कर सकता। इस प्रयास करें:

public IList<ICoupon> GetCouponsForSite(string siteSlug) 
{ 
    return _db.Coupons.Where(x => x.Site.slug == siteSlug) 
         .Select(x => new Coupon(x.id)).Cast<ICoupon>().ToList(); 
} 

इस के लिए मूल कारण यह है कि आप उदाहरण के एक class FancyCoupon : ICoupon के लिए था और डाल करने के लिए है कि एक List<Coupon> में तो यह असफल FancyCoupon कूपन (केवल ICoupon) से निकाले जाते हैं नहीं है कारण होगा की कोशिश की है, तो लेकिन यह List<ICoupon> में बस ठीक काम करना चाहिए। तो पहली नज़र में ऐसा लगता है कि यह एक दूसरे के रूप में उपयोग करने में सक्षम होना चाहिए, बल्कि दो प्रकार के बीच महत्वपूर्ण अंतर है।

कास्ट कॉल अनिवार्य रूप से सूची में पुन: सक्रिय होता है और नई सूची के लिए प्रत्येक को टाइप करता है (बोनट के तहत प्रदर्शन कारणों के लिए इसके लिए थोड़ा और है, लेकिन व्यावहारिक उद्देश्यों के लिए आप इस तरह से सोच सकते हैं)।

सामान्य प्रकार तर्क के रूप में Select में

+0

टाइपो: _db.Coupons.Where (x => x.Site.slug == साइटस्लॉग)। चयन करें (x => नया कूपन (x.id))। कास्ट करें() .सूची() ... लेकिन धन्यवाद, यह काम करता है। – Martin

+0

इनमें से किसी एक को काम करना चाहिए - कास्ट IQueryable और IENumerable इंटरफेस दोनों पर है ताकि आप किसी सूची में कनवर्ट करने से पहले या बाद में डाली जा सकें। यह थोड़ा अंतर बनाता है। – fyjham

+0

कैस्ट <>() एक आईनेमरेबल लौटाता है ... यही कारण है कि आपको। टोस्टिस्ट() (।) – Martin

0

इसका कारण यह है संकलक infers ICoupon है, और नहीं Coupon (टिप्पणियों से ठीक से अद्यतन किया गया),।

public IList<ICoupon> GetCouponsForSite(string siteSlug) 
{ 
    return _db.Coupons.Where(x => x.Site.slug == siteSlug) 
        .Select<?, ICoupon>(x => new Coupon(x.id)).ToList(); 
} 
: तो एक स्पष्ट डाली Select के बाद के बजाय के रूप में दूसरों के द्वारा प्रस्तावित (जो भी कुशल नहीं है क्योंकि यह सब से अधिक आइटम पुनरावृति करने की जरूरत है), तो आप भी निहित कास्टिंग (या अधिक सही ढंग से विचरण) सही Select generic types निर्दिष्ट करके उपयोग कर सकते हैं

(आप Coupons संग्रह का उचित प्रकार से ? को बदलने के लिए की जरूरत है।)

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