2009-05-23 17 views
22

यह मेरा कार्य है:LINQ: IENumerable [बेनामी टाइप] कैसे घोषित करें?

 private IEnumerable<string> SeachItem(int[] ItemIds) 
    { 
     using (var reader = File.OpenText(Application.StartupPath + @"\temp\A_A.tmp")) 
     { 
      var myLine = from line in ReadLines(reader) 
         where line.Length > 1 
         let id = int.Parse(line.Split('\t')[1]) 
         where ItemIds.Contains(id) 
         let m = Regex.Match(line, @"^\d+\t(\d+)\t.+?\t(item\\[^\t]+\.ddj)") 
         where m.Success == true 
         select new { Text = line, ItemId = id, Path = m.Groups[2].Value }; 
      return myLine; 
     } 
    } 

मुझे संकलन त्रुटि मिलती है, क्योंकि "myLine" एक आईनेमरेबल नहीं है [स्ट्रिंग] और मुझे नहीं पता कि आईनेमरेबल [बेनामी]

कैसे लिखना है "निहित रूप से नहीं कनवर्ट करें 'System.Collections.Generic.IEnumerable [AnonymousType # 1]' to 'System.Collections.Generic.IEnumerable [string]' "

उत्तर

15

आप IEnumerable<AnonymousType> की घोषणा नहीं कर सकते हैं:
अपने उदाहरण के लिए बदलने का प्रयास करें:

return myLine; 

करने के लिए। इसलिए यदि आप इस प्रकार का फ़ंक्शन घोषणा में उपयोग करना चाहते हैं, तो इसे सामान्य प्रकार बनाएं। या IENumerable<String> वापस करने के लिए अपनी क्वेरी को संशोधित करें और उस प्रकार के साथ चिपके रहें।

या निम्नलिखित चयन कथन का उपयोग कर IEnumerable<KeyValuePair<Int32, String>> वापस करें।

select new KeyValuePair<Int32, String>(id, m.Groups[2].Value) 
+2

जब आप कहते हैं कि "नया {...}" चुनें, तो आपने एक अनाम टाइप किया है। यदि कोई स्ट्रिंग चुनें, तो यह काम करना चाहिए। –

+0

नहीं, लेकिन आप IENumerable को वापस कर सकते हैं और CastByExample चाल का उपयोग कर सकते हैं। –

0

एक बात याद रखना होगा कि LINQ बयान deferred execution का उपयोग करें। इसका अर्थ यह है कि आपका LINQ कथन वास्तव में निष्पादित नहीं होता है जब तक कि आप इसे foreach कथन में फिर से चालू नहीं करते हैं या आप myLine पर .ToList() विधि को कॉल करते हैं। क्योंकि प्रकार का निर्माण समय कोई (जाना जाता है) का नाम है

return myLine.ToList(); 
+0

समस्या प्रक्रिया परिभाषा में है, इसलिए यह होना चाहिए "निजी सूची SeachItem (int [] ItemIds)", लेकिन है कि या तो काम नहीं करता। "परोक्ष प्रकार कनवर्ट नहीं कर सकता सूची [AnoynymousType # 1] सूची [स्ट्रिंग] के लिए। कृपया मुझे बताएं कि यह करना असंभव है या नहीं। :) –

8

SearchItem पर विधि हस्ताक्षर इंगित करता है कि विधि एक IEnumerable<string> रिटर्न लेकिन अनाम प्रकार अपने LINQ क्वेरी में घोषित प्रकार string की नहीं है। यदि आप एक ही विधि हस्ताक्षर रखना चाहते हैं, तो आपको अपनी क्वेरी को केवल string एस चुनने के लिए बदलना होगा। जैसे

return myLine.Select(a => a.Text); 

आप अपनी क्वेरी द्वारा चयनित डेटा लौटने पर जोर देते हैं, तो आप एक IEnumerable<object> लौट सकते हैं अगर आप

return myLine.Cast<object>(); 

के साथ अपने return बयान की जगह तो फिर तुम प्रतिबिंब का उपयोग की वस्तुओं का उपभोग कर सकते हैं।

लेकिन वास्तव में, यदि आप जिस तरीके से घोषित किए गए तरीके से बाहर एक अज्ञात प्रकार का उपभोग करने जा रहे हैं, तो आपको उस कक्षा के परिभाषित करना चाहिए जिसमें विधि उस वर्ग के IEnumerable को वापस कर दे। बेनामी प्रकार सुविधा हैं लेकिन वे दुर्व्यवहार के अधीन हैं।

5

आपका समारोह IEnumerable < स्ट्रिंग > वापस जाने के लिए, जब LINQ बयान आप को क्रियान्वित कर रहे हैं वास्तव में एक IEnumerable < टी > जहां टी एक संकलन समय उत्पन्न प्रकार है लौटने की कोशिश कर रहा है। बेनामी प्रकार हमेशा अज्ञात नहीं होते हैं, क्योंकि कोड संकलित होने के बाद वे एक विशिष्ट, ठोस प्रकार लेते हैं।

बेनामी प्रकार, हालांकि, संकलित होने तक वे क्षणिक हैं, केवल इनके द्वारा बनाए गए दायरे में ही उपयोग किया जा सकता है।उदाहरण में अपनी आवश्यकताओं का समर्थन करने के आपके द्वारा दी गई, मैं कहूंगा कि सरल समाधान के लिए एक सरल इकाई है कि आपकी क्वेरी के परिणामों को संग्रहीत करता है बनाने के लिए है:

public class SearchItemResult 
{ 
    public string Text { get; set; } 
    public int ItemId { get; set; } 
    public string Path { get; set; } 
} 

public IEnumerable<SearchItemResult> SearchItem(int[] itemIds) 
{ 
    // ... 
    IEnumerable<SearchItemResult> results = from ... select new SearchItemResult { ... } 
} 

हालांकि, यदि आपका अंतिम लक्ष्य किसी तरह का पुनः प्राप्त करने के लिए नहीं है

IEnumerable<string> lines = from ... select m.Groups[2].Value; 

मुझे आशा है कि LINQ, enumerables, और अनाम प्रकार के बारे में अपनी समझ को स्पष्ट मदद करता है: वस्तु, और आप केवल में, कहते हैं, पथ रुचि रखते हैं ... तो आप अभी भी एक IEnumerable < स्ट्रिंग > उत्पन्न कर सकते हैं। :)

+1

FYI: यह कहना सही नहीं है कि अज्ञात प्रकार उस क्षेत्र के लिए अनूठे हैं जो उन्हें बनाए गए हैं। अनाम प्रकार जो संरचनात्मक रूप से हैं एक ही समकक्ष में ssembly लेकिन दो अलग-अलग तरीकों से प्रयोग किया जाता है वास्तव में उन तरीकों से साझा किया जाता है। इस तथ्य का लाभ उठाने के लिए चालाक तरीके हैं, लेकिन मैं उन्हें अनुशंसा नहीं करता; यदि आपको दो तरीकों से एक प्रकार को साझा करने की आवश्यकता है, तो इसे नाममात्र बनाएं। –

+0

क्या माइक्रोसॉफ्ट प्रसिद्धि का एरिक लिपर्ट है? अब जब आपने बैग खोला है, तो आपको बिल्ली को बाहर निकालना होगा। आप गुमनाम प्रकार को स्कॉप्स में कैसे साझा करते हैं? ;) – jrista

+1

बहुत सावधानी से। आपको मूर्खतापूर्ण विधि प्रकार अनुमानों की चाल और कब्जे वाले बाहरी चर का उपयोग करना होगा। शायद मैं उस समय एक ब्लॉग करूंगा। –

6

मैं जरूरी यह सिफारिश करने नहीं कर रहा हूँ ... यह प्रकार प्रणाली की तोड़फोड़ की तरह है, लेकिन आप ऐसा कर सकता है:

1) IEnumerable (गैर सामान्य से एक वापस करने के लिए अपने विधि हस्ताक्षर बदल

0:

public static class Extensions{ 
    public static IEnumerable<T> CastByExample<T>(
      this IEnumerable sequence, 
      T example) where T: class 
    { 
     foreach (Object o in sequence) 
      yield return o as T; 
    } 
} 

3) तो इस तरह विधि कुछ कहते हैं:)

2) एक cast by example सहायक जोड़ने

और आप कर चुके हैं।

यह कुंजी यह तथ्य है कि यदि आप एक ही क्रम के साथ एक अनाम प्रकार बनाते हैं, तो दो स्थानों में प्रकार और संपत्ति के नाम पुन: उपयोग किए जाएंगे। इसे जानने से आप प्रतिबिंब से बचने के लिए जेनेरिक का उपयोग कर सकते हैं।

आशा इस मदद करता है एलेक्स

+0

चालाक। लेकिन वास्तव में, अगर कोई उस परेशानी पर जा रहा है, तो उसे सिर्फ घोषित कक्षा में डेटा को समाहित करना चाहिए। – jason

+2

जैसा कि मैंने कहा था कि मैं इसकी सिफारिश नहीं कर रहा हूं;) –

+0

... दिलचस्प बात यह है कि आप केवल एक बार इस समस्या पर जाते हैं, यानी एक बार जब आपके पास सहायक विस्तार विधि हो तो बार-बार उपयोग करना आसान होता है। हर जगह नए प्रकार के रोलिंग के विपरीत। वैसे भी यह .NET 4.0 में ट्यूपल के लिए एक नौकरी है –

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