संक्षिप्त जवाब:
उद्धरण ऑपरेटर एक ऑपरेटर है जो अपने ऑपरेंड पर क्लोजर शब्दार्थों को प्रेरित करता है । निरंतरता केवल मूल्य हैं।
उद्धरण और स्थिरांक के अलग-अलग अर्थ होते हैं और इसलिए एक अभिव्यक्ति पेड़ में अलग-अलग प्रतिनिधित्व होते हैं । दो अलग-अलग चीजों के लिए समान प्रतिनिधित्व होना बेहद आवश्यक है भ्रमित और बग प्रवण होता है।
लंबा जवाब:
निम्नलिखित को धयान मे रखते हुए:
(int s)=>(int t)=>s+t
बाहरी लैम्ब्डा योजक के लिए एक कारखाना है जो बाहरी लैम्ब्डा के पैरामीटर के लिए बाध्य है।
अब, मान लीजिए कि हम इसे एक अभिव्यक्ति वृक्ष के रूप में प्रस्तुत करना चाहते हैं जिसे बाद में संकलित और निष्पादित किया जाएगा। अभिव्यक्ति पेड़ का शरीर क्या होना चाहिए? यह इस बात पर निर्भर करता है कि आप संकलित राज्य को एक प्रतिनिधि या एक अभिव्यक्ति ट्री वापस करना चाहते हैं।
आइए निर्बाध मामले को खारिज करके शुरू करें। यदि हम इसे किसी प्रतिनिधि को लौटाने की इच्छा रखते हैं, तो यह प्रश्न कि क्या कोट या कॉन्स्टेंट का उपयोग करना एक मुदित बिंदु है:
var ps = Expression.Parameter(typeof(int), "s");
var pt = Expression.Parameter(typeof(int), "t");
var ex1 = Expression.Lambda(
Expression.Lambda(
Expression.Add(ps, pt),
pt),
ps);
var f1a = (Func<int, Func<int, int>>) ex1.Compile();
var f1b = f1a(100);
Console.WriteLine(f1b(123));
लैम्ब्डा में एक नेस्टेड लैम्ब्डा है; कंपाइलर आंतरिक लैम्ब्डा को एक फ़ंक्शन के प्रतिनिधि के रूप में उत्पन्न करता है जो बाहरी लैम्बडा के लिए उत्पन्न फ़ंक्शन की स्थिति पर बंद होता है। हमें इस मामले पर विचार करने की आवश्यकता है।
मान लें कि हम संकलित स्थिति को इंटीरियर के एक अभिव्यक्ति पेड़ को वापस करने की इच्छा रखते हैं । ऐसा करने के दो तरीके हैं: आसान तरीका और कठिन तरीका।
इसके बजाय कहना मुश्किल तरीका है
(int s)=>(int t)=>s+t
हम वास्तव में क्या मतलब है
(int s)=>Expression.Lambda(Expression.Add(...
और फिर के लिए अभिव्यक्ति पेड़ उत्पन्न कि उत्पादन इस गड़बड़ :
Expression.Lambda(
Expression.Call(typeof(Expression).GetMethod("Lambda", ...
ब्लाह ब्ला ब्ला, लैम्ब्डा बनाने के लिए प्रतिबिंब कोड की दर्जनों लाइनें। उद्धरण ऑपरेटर का उद्देश्य अभिव्यक्ति ट्री संकलक को यह बताना है कि हम चाहते हैं कि लैम्बडा को एक अभिव्यक्ति ट्री के रूप में माना जाए, न कि फ़ंक्शन के रूप में, अभिव्यक्ति ट्री जनरेशन कोड को स्पष्ट रूप से उत्पन्न किए बिना ।
आसान तरीका है:
var ex2 = Expression.Lambda(
Expression.Quote(
Expression.Lambda(
Expression.Add(ps, pt),
pt)),
ps);
var f2a = (Func<int, Expression<Func<int, int>>>)ex2.Compile();
var f2b = f2a(200).Compile();
Console.WriteLine(f2b(123));
और वास्तव में, यदि आप इस कोड को संकलित करते हैं और चलाते हैं तो आपको सही उत्तर मिलता है।
ध्यान दें कि उद्धरण ऑपरेटर वह ऑपरेटर होता है जो आंतरिक लंबो पर क्लोजर शब्दार्थों को प्रेरित करता है जो बाहरी चर का औपचारिक पैरामीटर का उपयोग करता है।
सवाल यह है कि क्यों नहीं उद्धरण को खत्म करें और इसे एक ही काम करें?
var ex3 = Expression.Lambda(
Expression.Constant(
Expression.Lambda(
Expression.Add(ps, pt),
pt)),
ps);
var f3a = (Func<int, Expression<Func<int, int>>>)ex3.Compile();
var f3b = f3a(300).Compile();
Console.WriteLine(f3b(123));
निरंतर बंद शब्दार्थ को प्रेरित नहीं करता है। क्यों करना चाहिए? आपने कहा कि यह एक निरंतर था । यह सिर्फ एक मूल्य है। यह कंपाइलर को सौंपने के लिए एकदम सही होना चाहिए; कंपाइलर को केवल उस मान का एक डंप उत्पन्न करने में सक्षम होना चाहिए जहां यह आवश्यक है।
चूंकि कोई क्लोजर प्रेरित नहीं है, अगर आप ऐसा करते हैं तो आपको "वैरिएबल 'का' प्रकार मिलेगा 'System.Int32' आह्वान पर अपवाद नहीं है"।
(एक तरफ: मैंने उद्धृत अभिव्यक्ति पेड़ों से प्रतिनिधि सृजन के लिए कोड जनरेटर की समीक्षा की है, और दुर्भाग्य से एक टिप्पणी जो मैंने 2006 में कोड में वापस रखी थी, अभी भी है। FYI करें, फहराया गया बाहरी पैरामीटर एक निरंतर में स्नैपशॉट है जब उद्धरण। अभिव्यक्ति ट्री को रनटाइम कंपाइलर द्वारा एक प्रतिनिधि के रूप में पुन: प्रस्तुत किया गया है। एक अच्छा कारण था कि मैंने कोड को इस तरह से लिखा था जो मुझे इस सटीक क्षण में याद नहीं है, लेकिन इसमें मूल्यों पर बंद होने का बुरा दुष्प्रभाव है बाहरी मापदंडों के चर पर बंद करने के बजाय। जाहिरा तौर पर उस कोड को विरासत में मिली टीम ने उस दोष को ठीक नहीं करने का फैसला किया, इसलिए यदि आप एक बंद किए गए बाहरी पैरामीटर के म्यूटेशन पर भरोसा कर रहे हैं, जो एक संकलित आंतरिक लैम्ब्डा में मनाया जा रहा है, तो आप निराश होने वाले हैं। हालाँकि, चूंकि यह दोनों के लिए एक बहुत बुरा प्रोग्रामिंग अभ्यास है (1) एक औपचारिक पैरामीटर को म्यूट करें और (2) एक बाहरी चर के उत्परिवर्तन पर भरोसा करते हैं, मैं आपको सलाह दूंगा कि आप इन दो खराब प्रोग्रामिंग प्रथाओं का उपयोग न करने के लिए अपने कार्यक्रम को बदलें। एक फिक्स के इंतजार में जो आगे दिखाई नहीं देता है। त्रुटि के लिए माफी।)
तो, सवाल दोहराने के लिए:
C # कंपाइलर नेस्टेड लैम्ब्डा एक्सप्रेशंस को अभिव्यक्ति ट्री में शामिल किया जा सकता है, जिसमें एक्सप्रेशन.Quote () के बजाय Expression.Constant () शामिल है, और कोई LINQ क्वेरी प्रोवाइडर जो कुछ क्वैरी लैंग्वेज (जैसे SQL) में एक्सप्रेशन ट्री प्रोसेस करना चाहता है ) एक कॉनटेंट एक्सप्रेशन के लिए एक विशेष उद्धरण नोड प्रकार के साथ एक UnaryExpression के बजाय टाइप एक्सप्रेशन के साथ देख सकता है, और बाकी सब समान होगा।
तुम सही हो। हम अर्थ संबंधी जानकारी को सांकेतिक शब्दों में बदल सकते हैं, जिसका अर्थ है " निरंतर मूल्य इस अर्थ को बंद करें" को एक ध्वज के रूप में स्थिर अभिव्यक्ति के प्रकार का उपयोग करके ।
"निरंतर" का अर्थ तब होगा "इस निरंतर मूल्य का उपयोग करें, जब तक कि प्रकार एक अभिव्यक्ति वृक्ष का प्रकार न हो और मान एक मान्य अभिव्यक्ति ट्री है, इस स्थिति में, इसके बजाय मान का उपयोग करें जो कि अभिव्यक्ति ट्री फिर से लिखने के परिणामस्वरूप होता है। दिए गए अभिव्यक्ति ट्री का इंटीरियर किसी भी बाहरी लंबोदा के संदर्भ में क्लोजर शब्दार्थ को प्रेरित करने के लिए है जो हम अभी हो सकते हैं।
लेकिन हम उस पागल चीज को क्यों करेंगे ? उद्धरण ऑपरेटर एक बिलकुल जटिल ऑपरेटर है , और यदि आप इसका उपयोग करने जा रहे हैं तो इसका उपयोग स्पष्ट रूप से किया जाना चाहिए । आप सुझाव दे रहे हैं कि पहले से ही कई दर्जन के बीच एक अतिरिक्त कारखाना विधि और नोड प्रकार को न जोड़ने के बारे में निंदनीय होने के लिए, कि हम स्थिरांक के लिए एक विचित्र कोने के मामले को जोड़ते हैं, ताकि स्थिरांक कभी-कभी तार्किक रूप से स्थिर होते हैं, और कभी-कभी उन्हें फिर से लिखा जाता है। बंद शब्दार्थ के साथ लंबोदर।
इसका कुछ हद तक अजीब प्रभाव भी होगा कि निरंतर का अर्थ "इस मूल्य का उपयोग" नहीं है। मान लीजिए कि कुछ विचित्र कारण के लिए आप ऊपर के तीसरे मामले को एक अभिव्यक्ति पेड़ को एक प्रतिनिधि में संकलित करना चाहते थे जो एक अभिव्यक्ति पेड़ को सौंपता है जिसमें एक बाहरी चर के लिए पुन: लिखित संदर्भ नहीं है? क्यों? शायद इसलिए कि आप अपने कंपाइलर का परीक्षण कर रहे हैं और केवल इस पर से निरंतर गुजरना चाहते हैं ताकि आप बाद में उस पर कुछ अन्य विश्लेषण कर सकें। आपका प्रस्ताव असंभव बना देगा; कोई भी स्थिरांक जो अभिव्यक्ति वृक्ष के प्रकार का होता है, उसकी परवाह किए बिना फिर से लिखा जाएगा। एक को एक उचित उम्मीद है कि "निरंतर" का अर्थ है "इस मूल्य का उपयोग करें"। "लगातार" एक "मैं जो कहता हूं वह करो" नोड है। निरंतर प्रोसेसर ' प्रकार के आधार पर कहने के लिए।
और ध्यान दें कि अब आप समझ का बोझ डाल रहे हैं (अर्थात, यह समझते हुए कि स्थिरांक में जटिल शब्दार्थ है, जिसका अर्थ है एक मामले में "स्थिर" और " प्रत्येक सिस्टम में एक ध्वज के आधार पर" बंद करने वाले शब्दार्थ को प्रेरित करता है ) प्रदाता जो केवल Microsoft प्रदाताओं पर नहीं, एक अभिव्यक्ति पेड़ का शब्दार्थ विश्लेषण करता है। उन तृतीय-पक्ष प्रदाताओं में से कितने इसे गलत पाएंगे?
"उद्धरण" एक बड़ा लाल झंडा लहरा रहा है जो कहता है "हे दोस्त, यहाँ देखो, मैं एक नेस्टेड लैम्ब्डा एक्सप्रेशन हूँ और अगर मैं एक बाहरी चर पर बंद हूँ तो मुझे निराला शब्दार्थ मिला है!" जबकि "कांस्टेंट" कह रहा है "मैं एक मूल्य से ज्यादा कुछ नहीं हूं, जैसा कि आप फिट देखते हैं, मेरा उपयोग करें।" जब कोई चीज जटिल और खतरनाक होती है तो हम उसे लहरदार लाल झंडे बनाना चाहते हैं, इस तथ्य को छिपाते हुए नहीं कि उपयोगकर्ता इस प्रकार की प्रणाली के माध्यम से खुदाई करता है ताकि यह पता लगाया जा सके कि यह मूल्य एक विशेष है या नहीं।
इसके अलावा, यह विचार कि अतिरेक से बचना भी एक लक्ष्य है, गलत है। निश्चित रूप से, अनावश्यक से बचना, अतिरेक को भ्रमित करना एक लक्ष्य है, लेकिन अधिकांश अतिरेक एक अच्छी बात है; अतिरेक स्पष्टता पैदा करता है। नए कारखाने के तरीके और नोड प्रकार सस्ते हैं । हम जितने चाहें उतने बना सकते हैं ताकि हर एक एक ऑपरेशन को साफ-सुथरा कर सके। हमें "इस बात का मतलब है कि जब तक इस क्षेत्र को इस चीज के लिए सेट नहीं किया जाता है, इस मामले में इसका मतलब कुछ और नहीं है"