2009-11-09 1 views
10

ExpressionTrees संकलक की तरह लग रहा कई व्यवहार में सी # कल्पना के साथ पास होना चाहिए, लेकिन विपरीत सी # किसी भी enum-type को decimal से रूपांतरण के लिए कोई समर्थन नहीं है:क्या यह एक अभिव्यक्ति ट्री बग है? # 2

using System; 
using System.Linq.Expressions; 

class Program 
{ 
    static void Main() 
    { 
    Func<decimal, ConsoleColor> converter1 = x => (ConsoleColor) x; 
    ConsoleColor c1 = converter1(7m); // fine 

    Expression<Func<decimal, ConsoleColor>> expr = x => (ConsoleColor) x; 

    // System.InvalidOperationException was unhandled 
    // No coercion operator is defined between types 
    // 'System.Decimal' and 'System.ConsoleColor'. 

    Func<decimal, ConsoleColor> converter2 = expr.Compile(); 

    ConsoleColor c2 = converter2(7m); 
    } 
} 

अन्य शायद ही कभी इस्तेमाल सी # स्पष्ट रूपांतरण, double -> enum-type की तरह मौजूद है और सी # विनिर्देशन में समझाया गया है, लेकिन decimal -> enum-type नहीं है। क्या यह एक बग है?

उत्तर

16

यह शायद एक बग है, और शायद यह मेरी गलती है। उसके लिए माफ़ करना।

दशमलव रूपांतरण प्राप्त करना संकलक पेड़ कोड को संकलक और रनटाइम में सही बनाने के सबसे कठिन भागों में से एक था क्योंकि दशमलव रूपांतरण वास्तव में रनटाइम में उपयोगकर्ता द्वारा परिभाषित रूपांतरण के रूप में कार्यान्वित किए जाते हैं, लेकिन अंतर्निहित रूपांतरण के रूप में व्यवहार किया जाता है कंपाइलर द्वारा। दशमलव इस संपत्ति के साथ एकमात्र प्रकार है, और इसलिए इन मामलों के लिए विश्लेषक में सभी प्रकार के विशेष उद्देश्य के गियर हैं। वास्तव में, विश्लेषक में IsEnumToDecimalConversion नामक एक विधि है जिसे शून्य करने योग्य एनम के विशेष मामले को शून्य करने योग्य दशमलव रूपांतरण को संभालने के लिए किया जाता है; काफी जटिल विशेष मामला।

बाधाएं अच्छी हैं कि मैं किसी अन्य मामले को दूसरी तरफ जाने पर विचार करने में असफल रहा, और परिणामस्वरूप खराब कोड उत्पन्न किया। नोट के लिए धन्यवाद; मैं इसे टेस्ट टीम में भेज दूंगा, और हम देखेंगे कि हम एक रेपो जा रहे हैं या नहीं। बाधाएं अच्छी हैं कि अगर यह पूरी तरह से बग बन जाती है, तो यह सी # 4 प्रारंभिक रिलीज के लिए तय नहीं की जाएगी; इस बिंदु पर हम केवल "उपयोगकर्ता को कंपाइलर द्वारा इलेक्ट्रोक्यूट किया जाता है" बग्स लेते हैं ताकि रिलीज स्थिर हो।

+0

मुझे नहीं पता था कि सी # भाषा बनाने में मनुष्यों को नुकसान पहुंचाया गया था :) –

+0

"दशमलव रूपांतरण वास्तव में रनटाइम में उपयोगकर्ता द्वारा परिभाषित रूपांतरण के रूप में कार्यान्वित किए जाते हैं, लेकिन संकलक द्वारा अंतर्निहित रूपांतरण के रूप में माना जाता है": इसका क्या अर्थ है , और यह इस तरह क्यों किया गया था? – Brian

+2

@ ब्रायन: जब आप एक प्रतिनिधित्व-बदलते रूपांतरण करते हैं, तो दो बार int कहें, एक आईएल निर्देश है जो वास्तव में उस रूपांतरण को करता है। जब आप डबल करने के लिए दशमलव करते हैं, तो हम वास्तव में रूपांतरण करने के लिए एक विधि को कॉल करने के लिए कोड उत्पन्न करते हैं; decimals के लिए कोई अंतर्निहित सीएलआर रूपांतरण निर्देश नहीं है। लेकिन एक * भाषा * परिप्रेक्ष्य से हम दशमलव रूपांतरणों को * प्रकट * करना चाहते हैं ताकि भाषा में अंतर्निहित रूपांतरण हो; हमारे पास अंतर्निर्मित और उपयोगकर्ता द्वारा प्रदत्त रूपांतरणों के लिए अलग-अलग नियम हैं। तो हमें दशकों के साथ दृश्यों के पीछे क्या हो रहा है, इसे छिपाने के लिए कुछ विशेष दृश्यों का निर्माण करना होगा। –

3

नहीं एक असली अभी तक इस सवाल का जवाब, मैं जांच कर रही है, लेकिन पहली पंक्ति के रूप में संकलित किया गया है:

Func<decimal, ConsoleColor> converter1 = x => (ConsoleColor)(int)x; 

आप पिछले लैम्ब्डा से एक अभिव्यक्ति बनाने की कोशिश करते हैं, यह काम करेंगे।

संपादित करें: सी # कल्पना, §6.2.2 में, आप पढ़ सकते हैं:

एक स्पष्ट गणन रूपांतरण दोनों के बीच प्रकार संसाधित किया जाता है द्वारा की अंतर्निहित प्रकार के रूप में किसी भी भाग लेने enum प्रकार इलाज enum-type, और उसके बाद परिणामी प्रकारों के बीच निहित या स्पष्ट संख्यात्मक रूपांतरण प्रदर्शन कर रहा है। उदाहरण के लिए, एक enum-type ई के साथ अंतर्निहित प्रकार के int, अंतर्निहित ई से बाइट में रूपांतरण को एक स्पष्ट संख्यात्मक रूपांतरण (§6.2.1) से int से बाइट तक संसाधित किया जाता है, और बाइट से रूपांतरण ई को को बाइट से int तक एक अंतर्निहित संख्यात्मक रूपांतरण (§6.1.2) के रूप में संसाधित किया जाता है।

इसलिए एनम से दशमलव तक स्पष्ट स्पष्ट रूप से नियंत्रित होते हैं, इसलिए आपको नेस्टेड कास्ट (int तो दशमलव) मिलता है। लेकिन मैं नहीं देख सकता कि क्यों संकलक लैम्ब्डा शरीर को दोनों मामलों में समान तरीके से पार्स नहीं करता है।

+2

कंपाइलर शायद किसी अन्य पास में नेस्टेड कास्ट उत्सर्जित करता है। इस मामले में, यह सिर्फ एक कनवर्ट नोड बनाता है जो रनटाइम पर विफल रहता है। चाहे यह एक कंपाइलर बग है जो नेस्टेड रूपांतरण या एक अभिव्यक्ति एपीआई बग को उत्सर्जित करना चाहिए जो दशमलव रूपांतरण को दशमलव समझना चाहिए पाठक को छोड़ दिया गया है। मैं एक के लिए सोचता हूं कि उचित कन्वर्ट नोड को उत्सर्जित करने के लिए यह सीएससी की ज़िम्मेदारी है। –

+0

मैं सहमत हूं।वास्तव में आपको "expr = lambda" रेखा पर संकलन त्रुटि मिलती है। तो संकलक घटना को अतिरिक्त कनवर्ट नोड या वास्तव में कुछ भी छोड़ने की कोशिश नहीं करता है; यह मानता है कि लैम्ब्डा शरीर अमान्य है, जो सी # spec के अनुसार नहीं है। –

+0

'डबल -> एनम-टाइप 'रूपांतरण सीएससी के लिए' डबल -> int' कनवर्ट नहीं किया गया है, बस सीधे 'डबल -> enum-type' और ExpressionTrees कंपाइलर इस ठीक को समझता है ... – ControlFlow