2010-11-25 12 views
6

निम्नलिखित कोड के साथ, मुझे "वापसी पुस्तकें" पर संकलन त्रुटि को "निहित रूप से डालने में असमर्थ" प्राप्त होता है; लाइन।मैं इंटरफेस प्रकार की सूची कैसे ठीक से वापस कर सकता हूं?

मैंने सोचा था कि क्योंकि पुस्तक वस्तुओं की एक सूची लौट रहा है जो प्रकाशन को लागू करता है, यह ठीक काम करना चाहिए?

public interface IPublication {} 

public class Book : IPublication {} 

public List<IPublication> GetBooks() 
{ 
    List<Book> books = new List<Book>(); 
    return books; 
} 

मुझे लगता है कि अगर मैं एक एकल पुस्तक को एक एकल प्रकाशन वस्तु के रूप में वापस करता हूं तो यह ठीक काम करता है। List<> का परिचय स्पष्ट कलाकारों की आवश्यकता है।

एक समाधान मैं उपयोग कर रहा हूँ के रूप में:

return books.Cast<IPublication>().ToList(); 

उत्तर

7

समस्या यह है कि List<IPublication> ऐसा कुछ है जो IPublication से प्राप्त किसी भी वर्ग को पकड़ सकता है। चूंकि संकलक पता नहीं है कि आप GetBooks() का परिणाम में एक Magazine डाल करने के लिए कोशिश नहीं करेंगे, तो आप इस तरह अपने समारोह में लिखने के लिए: अपने समारोह अपरिवर्तनीय सूची जो ऐसा नहीं करता रिटर्न

public List<IPublication> GetBooks() 
{ 
    List<IPublication> books = new List<IPublication>(); 
    // put only books in here 
    return books; 
} 

हैं सूचकांक द्वारा पहुँचा जा करने की जरूरत है (और आप सी # 4 पर हैं), तो आप इसे इस तरह लिख सकते हैं:

public IEnumerable<IPublication> GetBooks()   
{   
    List<Book> books = new List<Book>();   
    return books;   
} 

आप एक IEnumerable<T> लेकिन आप सी # 3 का उपयोग कर रहे लौट सकते हैं, तो आप cdhowie क्या पता चलता है क्या कर सकते हैं :

public IEnumerable<IPublication> GetBooks()   
{   
    List<Book> books = new List<Book>();   
    return books.Cast<IPublication>();   
} 

यदि आप सी # 2 का उपयोग कर रहे हैं, तो मैंने प्रस्तावित पहली विधि का उपयोग करना बेहतर होगा।

+1

आपके अंतिम उदाहरण में, आप 'पुस्तकें भी वापस कर सकते हैं। कैस्ट < प्रकाशन>(); 'सी # 3 और निचले स्तर पर। यह सूची को डुप्लिकेट नहीं करेगा, बल्कि बदले में एक गणना करेगा जो प्रत्येक आइटम को इंटरफ़ेस प्रकार में एक-एक करके डालेगा, जिसके लिए लगभग कोई स्मृति नहीं है। – cdhowie

+0

अच्छा बिंदु, cdhowie। यह केवल सी # 3 और उच्चतर पर काम करता है, हालांकि। संस्करण 2 में एक्सटेंशन विधियां या 'कास्ट' फ़ंक्शन नहीं था। बेशक आप 'संख्यात्मक' वर्ग आयात कर सकते हैं और इसे स्थिर रूप से कॉल कर सकते हैं, लेकिन शायद यह प्रयास के लायक नहीं है। – Gabe

0

मुझे लगता है कि आप के बजाय ग # 4.0 जहां हम covariance and contravariance है पुराने संस्करणों पर काम कर रहे हैं। तो आप केवल तत्व तत्व द्वारा तत्व तत्व को परिवर्तित कर सकते हैं।

+1

चूंकि सूची 'इंटरफ़ेस नहीं है, भिन्नता उसे यहां मदद नहीं करेगी। यहां तक ​​कि अगर वह एक इंटरफ़ेस पर स्विच करता है, तो भी वह उसकी मदद नहीं करेगा, क्योंकि 'IList ' एक परिवर्तनीय इंटरफ़ेस है ('टी' दोनों अपने कार्यों का इनपुट और आउटपुट है)। – Gabe

+0

@Gabe: माफ करना मैंने सवाल को सावधानी से नहीं पढ़ा, यह वास्तव में एक सह (एनटीए) भिन्नता प्रश्न जैसा दिखता है। लेकिन यहां मेरे पास एक और सवाल है: मुझे लगता है कि ओपी का कोड 'रिटर्न बुक' का उपयोग कर सही है। कैस्ट ()। ToList() ', तो उसका सवाल क्या है? –

+0

'books.Cast () के साथ समस्या। ToList()' यह है कि यह एक पूरी नई डुप्लिकेट सूची बनाता है। वह जानना चाहता है कि उस प्रतिलिपि को बनाने से कैसे बचें। – Gabe

2

यह एक सुरक्षित रूपांतरण नहीं है। कल्पना कीजिए कि अगर कोई आपकी किताबों की सूची में एक पत्रिका डालता है।

public class Library 
{ 
    public List<Book> books = new List<Book>(); 
    public List<IPublication> GetBooks() 
    { 
     return books; 
    } 
} 

कहीं और,

Magazine mag = ...; 
List<IPublication> pubs = someLibrary.GetBooks() 
pubs.Add(mag); 

.NET 4 में, आप एक IEnumerable<IPublication> रूप here वर्णित है, किसी भी नई वस्तुओं बनाने के बिना लौट सकते हैं,। cdhowie भी निम्न संस्करणों के लिए एक अच्छा काम देता है। बस .ToList() छोड़ें, और IEnumerable वापस करें।

मुझे एहसास है कि आपका विशेष मामला सुरक्षित है। लेकिन संकलक इसे सत्यापित नहीं कर सकता है।

1

अगर किसी को ऐसा करने के लिए थे आप अपने तरीके का उपयोग करने के लिए जब तक आप नेट 4.

पर हैं पर विचार करें करना होगा: क्रम List<IPublication> को List<Book> से रूपांतरण की अनुमति दी तो

public class Magazine : IPublication { } 

// Somewhere... 

var foo = something.GetBooks(); 
foo.Add(new Magazine()); 

, तो आपको पुस्तकों की सूची में पत्रिकाएं जोड़ने की अनुमति होगी! यह टाइप सिस्टम को तोड़ देता है, क्योंकि अगर कुछ List<Book> का संदर्भ था, तो यह Magazine में होने की उम्मीद नहीं करेगा, यह Magazine का इलाज करेगा, हालांकि यह एक पुस्तक थी, और फिर रनटाइम क्रैश (या बदतर - डेटा भ्रष्टाचार या असुरक्षित चीजें) आती हैं।

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