2012-07-20 16 views
9

के साथ चयन में अनुमान से नहीं किया जा सकता है मुझे नहीं लगता कि मैं कुछ भी गूढ़ कर रहा हूं, लेकिन मुझे इसके बारे में कोई अन्य प्रश्न नहीं दिख रहा है।सी # प्रकार तर्कों का उपयोग एकाधिक रिटर्न

निम्नलिखित कोड (मैंने इसे आवश्यकतानुसार घटा दिया है) सी # 4 में एक कंपाइलर त्रुटि उत्पन्न करता है। हालांकि, यह स्पष्ट होना चाहिए कि प्रकार तर्क क्या है - एक सबसे बड़ा आम संप्रदाय ("कक्षा ए") है जो कि है "फ्रोब" विधि के रिटर्न प्रकार में भी स्पष्ट रूप से परिभाषित किया गया है। क्या कंपाइलर लैम्ब्डा अभिव्यक्ति में सभी रिटर्न प्रकारों की सूची नहीं बना सकता है, अपने पूर्वजों को खोजने के लिए एक वंश पेड़ बना सकता है, और फिर उस विधि के अपेक्षित रिटर्न प्रकार के साथ मेल खाता है? विधि के लिए

प्रकार तर्क 'System.Linq.Enumerable.Select (System.Collections.Generic.IEnumerable, System.Func) के उपयोग से नहीं लगाया जा सकता। प्रकार तर्कों को स्पष्ट रूप से निर्दिष्ट करने का प्रयास करें।

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

namespace Sample 
{ 
    public abstract class A 
    { 
     private A(int index) { /* ... */ } 

     public sealed class A1 : A 
     { 
      public A1(string text, int index) 
       : base(index) 
      { /* ... */ } 
     } 

     public sealed class A2 : A 
     { 
      public A2(int index) 
       : base(index) 
      { /* ... */ } 
     } 

     private static Regex _regex = new Regex(@"(to be)|(not to be)"); 
     public static IEnumerable<A> Frob(string frobbable) 
     { 
      return _regex.Matches(frobbable) 
       .Cast<Match>() 
       .Select((match, i) => 
       { 
        if (match.Groups[1].Success) 
        { 
         return new A1(match.Groups[1].Value, i); 
        } 
        else 
        { 
         return new A2(i); 
        } 
       }); 
     } 
    } 
} 
+2

क्या आपने लौटने से पहले ए 1 और ए 2 को ए कास्टिंग करने का प्रयास किया है? लेकिन हाँ, मैं देख सकता हूं कि संकलक शिकायत क्यों करता है, यह जादूगर रूप से नहीं जानता है कि आप आम denominator वर्ग ए –

उत्तर

16

यह सी # 4 कल्पना की धारा 7.5.2.12 है कर देगा:

एक गुमनाम समारोह की अनुमानित वापसी प्रकार एफ प्रकार अनुमान और अधिभार संकल्प के दौरान प्रयोग किया जाता है। अनुमानित रिटर्न प्रकार केवल एक अज्ञात फ़ंक्शन के लिए निर्धारित किया जा सकता है जहां सभी पैरामीटर प्रकार ज्ञात हैं, या तो क्योंकि वे स्पष्ट रूप से दिए गए हैं, अज्ञात फ़ंक्शन रूपांतरण के माध्यम से प्रदान किए जाते हैं या एक संलग्न जेनेरिक विधि आमंत्रण पर टाइप अनुमान के दौरान अनुमानित होते हैं। अनुमानित रिटर्न प्रकार निम्नानुसार निर्धारित किया गया है:

  • यदि एफ का शरीर अभिव्यक्ति है, तो अनुमानित रिटर्न प्रकार का एफ उस अभिव्यक्ति का प्रकार है।
  • यदि एफ का शरीर ब्लॉक है और ब्लॉक के रिटर्न स्टेटमेंट में अभिव्यक्तियों का सेट सबसे अच्छा सामान्य प्रकार टी (§7.5.2.14) है, तो अनुमानित रिटर्न प्रकार का एफ टी
  • अन्यथा, ए ई

अनुभाग 7.5.2 के लिए वापसी प्रकार का अनुमान नहीं लगाया जा सकता है।14 यह है:

कुछ मामलों में, अभिव्यक्तियों के एक सेट के लिए एक सामान्य प्रकार का अनुमान लगाया जाना चाहिए। विशेष रूप से, तत्व प्रकारों को स्पष्ट रूप से टाइप किए गए सरणी और ब्लॉक निकायों के साथ गुमनाम कार्यों के रिटर्न प्रकार इस तरह से पाए जाते हैं।

Intuitively, तर्क के रूप में एक विधि

Tr M<X>(X x1 … X xm) 
Ei साथ

बुला लिए ई 1 ... एम इस निष्कर्ष बराबर होना चाहिए भाव का एक सेट दिया।

अधिक सटीक, अनुमान एक अपरिवर्तित प्रकार परिवर्तनीय एक्स के साथ शुरू होता है। आउटपुट प्रकार के संदर्भ प्रत्येक ईआई से एक्स तक बनाए जाते हैं। अंत में, एक्स तय होता है और, यदि सफल होता है, परिणामी प्रकार एस परिणामस्वरूप सबसे अच्छा सामान्य प्रकार होता है अभिव्यक्तियों के लिए। यदि ऐसा कोई एस मौजूद नहीं है, तो अभिव्यक्तियों का कोई सामान्य सामान्य प्रकार नहीं है।

तो, लगता है हमने:

void M<X>(X x1, Xx2) {} 

A1 a1 = new A1(); 
A2 a2 = new A2(); 
M(a1, a2); 

... कि X के लिए एक प्रकार का तर्क निर्धारित करने के लिए विफल हो जाएगा, तो वापस जाने के मूल्य अनुमान उसी तरह से विफल रहता है।

मुझे संदेह है कि यदि आपने को अपने रिटर्न मानों में A पर डाला है, तो यह काम करेगा।

+0

आह वहाँ सी # spec है। जॉन पोस्ट करने के लिए धन्यवाद। –

+1

बहुत सच है, या तो "ए" को कास्टिंग करना काम करता है। –

+0

तो मूल रूप से कल्पना यह कह रही है कि अनुमान प्रक्रिया दोनों मामलों में समान है। मैं देख सकता हु। लेकिन यह वास्तव में यह नहीं बताता कि "फिक्सिंग एक्स" की प्रक्रिया क्या है - यह वास्तविक समस्या है, कि संकलक दृढ़ संकल्प करने में सक्षम नहीं है। यह संभवतः संभव प्रकारों का सबसे विशिष्ट क्यों नहीं चुन सकता है, अगर यह जानता है कि एक तरफ ("ऑब्जेक्ट)" या अन्य ("ए) चुनने से कोई साइड इफेक्ट नहीं होगा? –

6

मैं वहाँ एक विशिष्ट सी # विनिर्देश खंड कहीं है कि इस तय है अनुमान लगा रहा हूँ। (संपादित करें: जॉन स्कीट ने इसे पाया और उन्हें अपने उत्तर में पोस्ट किया)

आमतौर पर, इस तरह के लैम्ब्डा (या टर्नरी ऑपरेशंस इत्यादि) को अस्पष्टता से बचने के लिए प्रत्येक चरण में एक ही सटीक वापसी प्रकार की आवश्यकता होती है। उदाहरण के लिए, आपके मामले में, क्या आप A या Object टाइप करना चाहते हैं? जब आप मिश्रण में इंटरफेस या विरासत के कई स्तर फेंकते हैं तो और भी मजेदार।

इस मामले में सबसे अच्छा शर्त बस A लिखें या एक अस्थायी चर में संग्रहीत करना अपनी वापसी कथनों में से प्रत्येक कास्ट करने के लिए है:

if (match.Groups[1].Success) 
    return (A)(new A1(match.Groups[1].Value, i)); 
else 
    return (A)(new A2(i)); 

या

A returnValue; 

if (match.Groups[1].Success) 
    returnValue = new A1(match.Groups[1].Value, i); 
else 
    returnValue = new A2(i); 

return returnValue; 

संपादित करें: यदि आप अनुमानित प्रकार के बिना ठीक है, आप Select क्वेरी के साथ स्पष्ट रूप से कॉल कर सकते हैं:

.Cast<Match>() 
.Select<Match, A>((match, i) => 
{ 
    if (match.Groups[1].Success) 
     return new A1(match.Groups[1].Value, i); 
    else 
     return new A2(i); 
}); 

फिर संकलक बस सुनिश्चित करें कि अपनी वापसी प्रकार A साथ परोक्ष संगत कर रहे हैं (जो वे कर रहे हैं)

+0

नहीं होना चाहते हैं; वापसी प्रकारों को इंडेंटिकल होने की आवश्यकता नहीं है। – SLaks

+1

@SLaks मुझे लगता है कि वे टाइप अनुमान के लिए क्या करते हैं। अगर लार्स ने स्पष्ट रूप से टाइप किया था '' का चयन करें, तो वे जो भी ऑब्जेक्ट्स स्पष्ट रूप से उन्हें कास्ट किए बिना टाइप 'ए' के रूप में माना जा सकता है। –

+0

सहायक पोस्ट के लिए धन्यवाद - लेकिन यह सिर्फ कामकाज है, यह जवाब नहीं है कि "क्यों" मुझे अनावश्यक काम की तरह लगता है। मुझे "कंपाइलर इस तरह से स्मार्ट क्यों नहीं हो सकता" पहलू में अधिक दिलचस्पी है। –

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