2011-10-14 12 views
43

मुझे आश्चर्य है कि Expression<> के अंदर एक प्रतिनिधि को लपेटने के बीच वास्तव में क्या अंतर है और नहीं?अभिव्यक्ति वर्ग का उद्देश्य क्या है?

मैं देख रहा हूं Expression<Foo> लिंकक के साथ बहुत उपयोग किया जा रहा है, लेकिन अब तक मुझे कोई ऐसा लेख नहीं मिला है जो इसके बीच का अंतर बताता है, और सिर्फ एक प्रतिनिधि का उपयोग करता है।

उदा।

Func<int, bool> Is42 = (value) => value == 42; 

बनाम

Expression<Func<int, bool>> Is42 = (value) => value == 42; 

उत्तर

48

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

एक लैम्ब्डा को अभिव्यक्ति के रूप में संग्रहीत करके, आप एक अभिव्यक्ति वृक्ष संग्रहित कर रहे हैं जो प्रतिनिधि का प्रतिनिधित्व करता है। इसे अन्य चीजों को करने के लिए छेड़छाड़ की जा सकती है जैसे कि इसके पैरामीटर बदलना, शरीर को बदलना और इसे कुछ मूल रूप से अलग करना। इसे किसी प्रतिनिधि को भी संकलित किया जा सकता है ताकि यदि आप चाहें तो इसे कॉल कर सकते हैं। आप यह देखने के लिए आसानी से अभिव्यक्ति का निरीक्षण कर सकते हैं कि इसके पैरामीटर क्या हैं, यह क्या करता है और यह कैसे करता है। यह ऐसा कुछ है जो एक क्वेरी प्रदाता किसी अन्य भाषा में एक अभिव्यक्ति को समझने और अनुवाद करने के लिए उपयोग कर सकता है (जैसे एक संबंधित अभिव्यक्ति वृक्ष के लिए एक SQL क्वेरी लिखें)।

कोड को उत्सर्जित करने से अभिव्यक्तियों का उपयोग करके गतिशील रूप से एक प्रतिनिधि बनाना भी बहुत आसान है। आप अपने कोड को उच्च स्तर पर अभिव्यक्ति के रूप में सोच सकते हैं जो कम स्तर पर जाने के बजाय एक कंपाइलर दृश्य कोड के समान है और आईएल निर्देशों के रूप में अपना कोड देखें।

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

+0

यह मेरे लिए बिल्कुल स्पष्ट है, बहुत धन्यवाद :-) – Steffen

13

Func<> सिर्फ एक प्रतिनिधि प्रकार है। एक अभिव्यक्ति operations के पूरे पेड़ का एक रनटाइम प्रतिनिधित्व जो वैकल्पिक रूप से, किसी प्रतिनिधि में रनटाइम पर संकलित किया जा सकता है। यह पेड़ है जिसे एसक्यूएल स्टेटमेंट जेनरेट करने या अन्य चालाक चीजों को उत्पन्न करने के लिए लिंक-टू-एसक्यूएल जैसे अभिव्यक्ति पार्सर्स द्वारा पार्स किया गया है। जब आप एक अभिव्यक्ति प्रकार में लैम्ब्डा आवंटित करते हैं, तो संकलक इस अभिव्यक्ति के पेड़ के साथ-साथ सामान्य आईएल कोड उत्पन्न करता है। More on expression trees

4

बेस क्लास प्रदान करता है जिसमें से अभिव्यक्ति वृक्ष नोड्स का प्रतिनिधित्व करने वाले वर्ग व्युत्पन्न होते हैं।

System.Linq.Expressions.BinaryExpression 
System.Linq.Expressions.BlockExpression 
System.Linq.Expressions.ConditionalExpression 
System.Linq.Expressions.ConstantExpression 
System.Linq.Expressions.DebugInfoExpression 
System.Linq.Expressions.DefaultExpression 
System.Linq.Expressions.DynamicExpression 
System.Linq.Expressions.GotoExpression 
System.Linq.Expressions.IndexExpression 
System.Linq.Expressions.InvocationExpression 
System.Linq.Expressions.LabelExpression 
System.Linq.Expressions.LambdaExpression 
System.Linq.Expressions.ListInitExpression 
System.Linq.Expressions.LoopExpression 
System.Linq.Expressions.MemberExpression 
System.Linq.Expressions.MemberInitExpression 
System.Linq.Expressions.MethodCallExpression 
System.Linq.Expressions.NewArrayExpression 
System.Linq.Expressions.NewExpression 
System.Linq.Expressions.ParameterExpression 
System.Linq.Expressions.RuntimeVariablesExpression 
System.Linq.Expressions.SwitchExpression 
System.Linq.Expressions.TryExpression 
System.Linq.Expressions.TypeBinaryExpression 
System.Linq.Expressions.UnaryExpression 

http://msdn.microsoft.com/en-us/library/system.linq.expressions.expression.aspx

अभिव्यक्ति पेड़ LINQ अभिव्यक्ति है कि विश्लेषण किया जा सकता है और उदाहरण के लिए SQL क्वेरी में बदल गया प्रतिनिधित्व करता है।

4

Expression Trees आपको अपने कोड में अभिव्यक्ति के अंदर कोड का निरीक्षण करने की अनुमति देता है।

उदाहरण के लिए, यदि आप इस अभिव्यक्ति को पारित करते हैं: o => o.Name, आपका कोड यह पता लगा सकता है कि Name संपत्ति अभिव्यक्ति के भीतर उपयोग की जा रही थी।

9

अन्य उत्तर समझने के लिए, अगर आप उन 2 भाव संकलन और संकलक उत्पन्न कोड पर नजर है, यह मैं आप क्या देखेंगे:

Func<int, bool> Is42 = (value) => value == 42;

Func<int, bool> Is42 = new Func<int, bool>((@value) => value == 42); 


Expression<Func<int, bool>> Is42 = (value) => value == 42;

ParameterExpression[] parameterExpressionArray; 
ParameterExpression parameterExpression = Expression.Parameter(typeof(int), "value"); 
Expression<Func<int, bool>> Is42 = Expression.Lambda<Func<int, bool>>(Expression.Equal(parameterExpression, Expression.Constant(42, typeof(int))), new ParameterExpression[] { parameterExpression }); 
+0

ठीक है, आप किस बिंदु को बनाने की कोशिश कर रहे हैं ? – Phil

+4

वह पूछ रहा था कि मतभेद क्या थे और जेनरेट कोड अंतरों के आत्म-व्याख्यात्मक थे। – Ucodia

2

जो कुछ भी लिखा है (जो पूरी तरह से सही है) मैं इसे Expression कक्षा के माध्यम से जोड़ दूंगा, आप रनटाइम पर नए तरीके बना सकते हैं। कुछ सीमाएं हैं। सी # में आप जो कुछ भी कर सकते हैं, वह Expression पेड़ में नहीं किया जा सकता है (कम से कम .NET 3.5 में। .NET 4.0 के साथ उन्होंने Expression "प्रकार" की एक बड़ी संख्या को जोड़ा है)। इसका उपयोग गतिशील क्वेरी बनाने के लिए (उदाहरण के लिए) हो सकता है और इसे LINQ-to-SQL पर पास कर सकता है या उपयोगकर्ता के इनपुट के आधार पर कुछ फ़िल्टरिंग कर सकता है ... (यदि आप चाहें तो आप हमेशा कोडडॉम के साथ ऐसा कर सकते हैं LINQ-to-SQL के साथ एक गतिशील विधि असंगत थी, लेकिन सीधे आईएल कोड उत्सर्जित करना काफी कठिन है :-))

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