2010-02-02 13 views

उत्तर

227

अद्यतन: यह प्रश्न the subject of my blog on 12 April 2010 था। मनोरंजक प्रश्न के लिए धन्यवाद!

अभ्यास में, कोई अंतर नहीं है।

सिद्धांत में कोई अंतर हो सकता है। सी # विनिर्देश में तीन दिलचस्प बिंदु हैं जहां यह एक अंतर पेश कर सकता है।

सबसे पहले, अज्ञात कार्यों का रूपांतरण प्रकार और अभिव्यक्ति पेड़ को प्रतिनिधि करने के लिए। निम्नलिखित पर विचार करें:

Func<int> F1() { return()=>1; } 
Func<int> F2() { return (()=>1); } 

F1 स्पष्ट रूप से कानूनी है। F2 है? तकनीकी रूप से, नहीं। The spec धारा 6.5 में कहता है कि एक संगत प्रतिनिधि प्रकार के लिए लैम्ब्डा अभिव्यक्ति से एक रूपांतरण है। क्या यह लैम्ब्डा अभिव्यक्ति है? नहीं। यह कोष्ठक अभिव्यक्ति है जिसमें लैम्ब्डा अभिव्यक्ति शामिल है।

विज़ुअल सी # कंपाइलर यहां एक छोटा सा उल्लंघन उल्लंघन करता है और आपके लिए ब्रांड्स को छोड़ देता है।

दूसरा:

int M() { return 1; } 
Func<int> F3() { return M; } 
Func<int> F4() { return (M); } 

F3 कानूनी है। F4 है? सं। धारा 7.5.3 बताता है कि एक संश्लेषित अभिव्यक्ति में एक विधि समूह नहीं हो सकता है। फिर, आपकी सुविधा के लिए हम विनिर्देश का उल्लंघन करते हैं और रूपांतरण की अनुमति देते हैं।

तीसरा:

enum E { None } 
E F5() { return 0; } 
E F6() { return (0); } 

F5 कानूनी है। F6 है? नहीं। कल्पना बताती है कि शाब्दिक शून्य से किसी भी गणना प्रकार में रूपांतरण होता है। "(0)" शाब्दिक शून्य नहीं है, यह एक संश्लेषण है जिसके बाद शाब्दिक शून्य होता है, जिसके बाद एक कोष्ठक होता है। हम यहां विनिर्देश का उल्लंघन करते हैं और असल में शून्य के बराबर समय निरंतर अभिव्यक्ति संकलित करते हैं, न कि केवल शाब्दिक शून्य।

इसलिए हर मामले में, हम आपको इससे दूर जाने की अनुमति देते हैं, भले ही तकनीकी रूप से ऐसा करना अवैध है।

+2

@ एरिक लिपर्ट: क्यों spec उल्लंघन? मैं देखता हूं कि आप सुविधा के लिए कहते हैं लेकिन आप आसानी से बनाम spec का उल्लंघन करने के संतुलन का वजन कैसे करते हैं? क्या यह एक बग था जो सुविधा के लिए एक विशेषता बन गई? :-) – jason

+0

मुझे लगता है कि आखिरी शब्द जिसका मतलब है * अवैध *? –

+12

@ जेसन: मेरा मानना ​​है कि पहले दो मामलों में spec उल्लंघन केवल त्रुटियां हैं जिन्हें कभी पकड़ा नहीं गया था। शुरुआती बाध्यकारी पास ऐतिहासिक रूप से अभिव्यक्तियों को समय-समय पर अनुकूलित करने के बारे में बहुत आक्रामक रहा है, और इसके परिणामों में से एक यह है कि कोष्ठक को बहुत जल्दी पहले फेंक दिया जाता है, इससे पहले कि उन्हें होना चाहिए। हर मामले में काफी कुछ, यह सब ऐसा प्रोग्राम बनाता है जो सहज तरीके से स्पष्ट तरीके से काम करते हैं, इसलिए मैं इसके बारे में बहुत चिंतित नहीं हूं। तीसरे मामले का विश्लेषण यहां है: http://blogs.msdn.com/ericlippert/archive/2006/03/28/the-root-of-all-evil-part-one.aspx –

26

नहीं, वहाँ कोई वाक्य के अलावा अन्य अंतर है:

return myRV; 

वहाँ एक अंतर कर रही है।

3

इस तरह के सवालों के जवाब देने का एक अच्छा तरीका है प्रतिबिंबक का उपयोग करना और देखें कि आईएल क्या उत्पन्न होता है। आप कंपाइलर ऑप्टिमाइज़ेशन और असेंबली को कम करने के बारे में बहुत कुछ सीख सकते हैं।

+6

यह निश्चित रूप से एक विशिष्ट मामले के लिए प्रश्न का उत्तर देगा, लेकिन यह आवश्यक रूप से स्थिति की पूरी तरह से प्रतिनिधि नहीं होगा। – Beska

+0

असहमत। यह व्यक्ति को प्रश्न का उत्तर देने की दिशा देता है। – Bryan

40

कोने मामलों रहे हैं कोष्ठकों की उपस्थिति कार्यक्रम व्यवहार पर असर पड़ सकता है जब:

1.

using System; 

class A 
{ 
    static void Foo(string x, Action<Action> y) { Console.WriteLine(1); } 
    static void Foo(object x, Func<Func<int>, int> y) { Console.WriteLine(2); } 

    static void Main() 
    { 
     Foo(null, x => x()); // Prints 1 
     Foo(null, x => (x())); // Prints 2 
    } 
} 

2.

using System; 

class A 
{ 
    public A Select(Func<A, A> f) 
    { 
     Console.WriteLine(1); 
     return new A(); 
    } 

    public A Where(Func<A, bool> f) 
    { 
     return new A(); 
    } 

    static void Main() 
    { 
     object x; 
     x = from y in new A() where true select (y); // Prints 1 
     x = from y in new A() where true select y; // Prints nothing 
    } 
} 

3.

using System; 

class Program 
{ 
    static void Main() 
    { 
     Bar(x => (x).Foo(), ""); // Prints 1 
     Bar(x => ((x).Foo)(), ""); // Prints 2 
    } 

    static void Bar(Action<C<int>> x, string y) { Console.WriteLine(1); } 
    static void Bar(Action<C<Action>> x, object y) { Console.WriteLine(2); } 
} 

static class B 
{ 
    public static void Foo(this object x) { } 
} 

class C<T> 
{ 
    public T Foo; 
} 

आशा है कि आप पहले रहेंगे अभ्यास में यह देखें।

+0

मेरे प्रश्न का बिल्कुल जवाब नहीं है, लेकिन फिर भी दिलचस्प - धन्यवाद। – chris

+1

क्या आप समझा सकते हैं कि यहां 2 में क्या हो रहा है? – Eric

+1

आपको यह बताएं कि यह व्यवहार क्यों होता है। –

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