मैं लंबोदर अभिव्यक्ति में अशक्त प्रसार संचालक का उपयोग क्यों नहीं कर सकता?


103

मैं अक्सर अपने कोड में अशक्त प्रचारक ऑपरेटर का उपयोग करता हूं क्योंकि यह मुझे अधिक पठनीय कोड देता है, विशेष रूप से लंबे प्रश्नों में मुझे उपयोग किए जाने वाले प्रत्येक एकल वर्ग को शून्य-चेक ​​करने की आवश्यकता नहीं है।

निम्न कोड एक संकलित त्रुटि को फेंकता है जिसे हम लंबोदर में अशक्त प्रसार संचालक का उपयोग नहीं कर सकते हैं।

var cnt = humans.AsQueryable().Count(a => a.House?[0].Price == 5000);

त्रुटि :

CS8072 त्रुटि एक ट्री ट्री लैम्ब्डा में अशक्त प्रसार संचालक नहीं हो सकता है।

यदि कोड वास्तव में कुछ और नहीं कर सकता है तो कोड का अनुसरण करने के लिए कोड के ऊपर कोड # आसानी से अनुवाद कर सकता है!

var cnt = humans.AsQueryable().Count(a => a.House != null && a.House[0].Price == 5000);

मैं उत्सुक हूं कि C # कुछ नहीं करता है और बस एक संकलक त्रुटि फेंकता है?


4
Foo?.Barके बराबर नहीं है Foo != null ? Foo.Bar : nullक्योंकि Fooएक बार अशक्त-प्रसार ऑपरेटर के साथ और दो बार सशर्त के साथ मूल्यांकन किया जाता है, इसलिए सभी मामलों में अनुवाद सही नहीं होगा।
लुकास ट्रेज़न्यूस्की

3
ध्यान दें कि यदि ईएफ के लिए इसका कोड है, तो संभावना है कि आपको वास्तव में अशक्त प्रचारक की आवश्यकता नहीं है, क्योंकि जब एक प्रश्न को SQL कॉल में परिवर्तित किया जाता है, तो SQL nulls को फेंक नहीं देता है :-)
xanatos

NB: यह लिखने के var q = from c in Categories join p in Products on c equals p.Category into ps from p in ps.DefaultIfEmpty() select new { Category = c, ProductName = (p?.ProductName)??"(No products)"};बजाय लिखने के लिए उपयोगी होगा ProductName = (p == null) ? "(No products)" : p.ProductNameक्योंकि EF वर्तमान में ?.ऑपरेटर का समर्थन नहीं करता है ।
मैट

जवाबों:


72

यह जटिल है क्योंकि ट्री ट्री लैम्ब्डा (डेलिगेट लैम्ब्डा के विपरीत) की व्याख्या पहले से मौजूद LINQ प्रदाताओं द्वारा की जाती है जो अभी तक अशक्त प्रचार का समर्थन नहीं करते हैं।

एक सशर्त अभिव्यक्ति में परिवर्तित करना हमेशा सटीक नहीं होता है क्योंकि कई मूल्यांकन होते हैं जबकि ?.उदाहरण के लिए केवल एक ही मूल्यांकन होता है:

customer.Where(a => c.Increment()?.Name) // Written by the user 
customer.Where(a => c.Increment() == null ? null : c.Increment().Name) // Incorrectly interpreted by an old LINQ provider

आप प्रासंगिक में गहरी जा सकते हैं CodePlex पर चर्चा जहां 3 समाधान की पेशकश कर रहे: NullPropagationExpression, ConditionalExpressionऔर एक संकर


26
मुझे निश्चित रूप से आश्चर्य नहीं होगा यदि कुछ क्वेरी प्रदाता इसका समर्थन नहीं कर सकते हैं, लेकिन यह सी # भाषा का समर्थन नहीं करने का एक कारण नहीं है।
सर्व

18
तथ्य यह है कि कुछ क्वेरी प्रदाताओं अभी तक नहीं है इसे समर्थन पर रोक लगाने का कोई कारण नहीं है सब से क्वेरी प्रदाताओं कभी इसका इस्तेमाल करने में सक्षम होने।
20

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

8
पूरे बिंदु के Expressionकोड के रूप में अर्थ की दृष्टि से सभी सी # भाव का प्रतिनिधित्व करने में सक्षम होना है। यह भाषा के कुछ छोटे उपसमूह होने के लिए डिज़ाइन नहीं किया गया है।
सेरी

7
ऐसा लगता है कि अभी भी 3 साल बाद हल नहीं हुआ है - क्या माइक्रोसॉफ्ट को अब तक समय नहीं मिल पाया है? उन्हें लगता है कि इन दिनों C # में नई सुविधाओं को लागू करने के लिए एक बहाने के रूप में समय और संसाधनों का उपयोग करने की बुरी आदत है।
नेटमैज
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.