2012-06-16 12 views
18

मुझे रीफैक्टर-सुरक्षित तरीके से रन-टाइम पर स्थानीय चर (और पैरामीटर) के नामों को पुनर्प्राप्त करने में रुचि है।लैम्ब्डा अभिव्यक्तियों के माध्यम से रन-टाइम पर स्थानीय चर (और पैरामीटर) के नाम प्राप्त करना

public static string GetVariableName<T>(Expression<Func<T>> variableAccessExpression) 
{ 
    var memberExpression = variableAccessExpression.Body as MemberExpression; 
    return memberExpression.Member.Name; 
} 

... जो एक लैम्ब्डा अभिव्यक्ति के माध्यम से कब्जा कर लिया वैरिएबल का नाम देता है:

static void Main(string[] args) 
{ 
    Console.WriteLine(GetVariableName(() => args)); 
    // Output: "args" 

    int num = 0; 
    Console.WriteLine(GetVariableName(() => num)); 
    // Output: "num" 
} 

हालांकि, यह केवल काम करता है क्योंकि सी # संकलक किसी भी स्थानीय चर को बढ़ावा देता है (और मैं निम्नलिखित विस्तार विधि है पैरामीटर) जो दृश्यों के पीछे एक कंपाइलर-जेनरेट क्लास के भीतर समान नाम के उदाहरण चर के लिए अनाम कार्यों में कैप्चर किए जाते हैं (प्रति Jon Skeet)। यदि यह मामला नहीं था, तो Body से MemberExpression का कास्ट विफल हो जाएगा, क्योंकि MemberExpression फ़ील्ड या संपत्ति पहुंच का प्रतिनिधित्व करता है।

क्या यह चरम पदोन्नति दस्तावेज व्यवहार है, या यह ढांचा के अन्य संस्करणों में परिवर्तन के अधीन एक कार्यान्वयन विस्तार है?

नोट: यह प्रश्न my former one on argument validation का सामान्यीकरण है।

+0

आप यहां विकल्पों को पकड़ सकते हैं: http://stackoverflow.com/questions/72121/finding-the-variable-name-passed-to-a-function-in-c-sharp लेकिन फिर फिर से अनियंत्रित। अज्ञात प्रकार का दृष्टिकोण बहुत तेज़ है .. – nawfal

उत्तर

1

AFAIK, यह एक कार्यान्वयन विस्तार है।

हालांकि, मुझे लगता है कि आप शर्त लगा सकते हैं कि यह वास्तव में नहीं बदलेगा।

मैंने अभी वीएस2012 आरसी में परीक्षण किया है और यह अपेक्षा के अनुसार काम करता है - इसलिए आप कम से कम कुछ वर्षों से सुरक्षित हैं।

+1

मोनो और ढांचे के वैकल्पिक कार्यान्वयन के बारे में क्या? वे कार्यान्वयन विवरण के साथ कुछ स्वतंत्रता लेने के लिए जाने जाते हैं (उदाहरण के लिए, वे .NET Framework की तुलना में [स्मृति मॉडल पर लूसर अर्थशास्त्र] प्रदान करते हैं (http://stackoverflow.com/a/10608993/1149773)। भले ही वे आज भी उसी कार्यान्वयन का उपयोग करें, वे भविष्य में रिलीज में ऐसा नहीं कर सकते हैं। – Douglas

+1

फिर भी, वीएस2012 पर जांच के लिए धन्यवाद :-) यह जानना अच्छा है कि कम से कम माइक्रोसॉफ्ट अभी तक इसे तोड़ नहीं देगा। – Douglas

+0

मुझे मोनो के बारे में पता नहीं है - आपको जांचना होगा। यह वास्तव में टॉस अप है: क्या आपको लगता है कि आपका समाधान तोड़ने का मौका है, आपको 'चेक नॉटनुल' ("तर्क", तर्क) ' –

4

यह एक व्यवहार है जिसे आपको पर भरोसा करना चाहिए।

Abuse of C# lambda expressions or Syntax brilliance?

पर एक नजर डालें अब एरिक Lippert जो सी # डिजाइन टीम पर है से टिप्पणी पढ़ें। इनमें शामिल हैं:

मैंने अभी एंडर्स (और बाकी डिज़ाइन टीम) से पूछा कि वे सोचा। चलो बस का कहना है कि परिणाम

और

क्यों इस भयंकर है का सवाल है, हम साथ unobvious, चालाक (याद शुरू कर सकता है एक परिवार के अनुकूल अखबार में प्रिंट करने योग्य नहीं होगा, चतुर बुरा है , चतुर कोड बनाए रखने के लिए कठिन है), सभी नहीं पर द्वारा डिजाइन उपयोग lambdas के डिजाइनर, द्वारा परिकल्पित मामलों के भीतर धीमी गति से, भंगुर, unportable, और अनावश्यक

इन बयानों से मैं कहूंगा कि यह एक दस्तावेज या समर्थित व्यवहार नहीं बन जाएगा।

+0

+1: यह मुझे सही दिशा में इंगित करता है कि उत्तर क्या होगा। हालांकि, जुड़े प्रश्न में, 'एट्रिब्यूट्स (शैली => "चौड़ाई: 100%")' लैम्ब्डा का उपयोग केवल इसलिए किया जाता है क्योंकि यह परंपरागत रूप से सौंदर्य/रूप से बेहतर दिखता है। "(" शैली "," चौड़ाई: 100% ") 'वाक्यविन्यास, और इसलिए नहीं क्योंकि यह किसी भी कार्यक्षमता को अन्यथा अनुपलब्ध करता है, लिपर्ट की टिप्पणी को न्यायसंगत बनाता है कि यह" अनावश्यक "है। (जारी ...) – Douglas

+3

मेरे प्रश्न में, मुझे लगता है कि सदस्य/परिवर्तनीय नाम lambdas का उपयोग करने के लिए एक मजबूत उपयोग-मामला है। मुझे लगता है कि सदस्य/परिवर्तनीय नामों को स्ट्रिंग में एम्बेड करने का .NET अभ्यास - जैसे 'PropertyChangedEventArgs' और' ArgumentException' '- मेरे प्रस्तावित विकल्प से अधिक "भयंकर" है। – Douglas

+0

प्रिज्म 4 RaisePropertyChanged के अपने अभिव्यक्ति वृक्ष अधिभार के लिए इसी चीज़ का उपयोग करता है। – JKor

12

अद्यतन: यह नहीं रह गया है सी # 6 है, जो इस तरह के परिदृश्य (MSDN देखें) को संबोधित करने के nameof ऑपरेटर शुरू की है से एक मुद्दा है।

ऐसा प्रतीत होता है कि मेरे प्रश्न का उत्तर नहीं है; सुविधा गैर-मानकीकृत है। मुझे मूल रूप से संदेह होने की स्थिति में भी खून बह रहा है; न केवल कब्जे वाले चर के प्रचार को गैर-मानकीकृत किया जाता है, बल्कि अज्ञात कार्यों को उनके अभिव्यक्ति वृक्ष प्रस्तुतिकरणों में परिवर्तित करने का संपूर्ण विनिर्देश भी है।

इस का निहितार्थ यह है कि इस तरह के नीचे, इसकी गारंटी नहीं कर रहे हैं के रूप में भी सीधा गुमनाम काम करता है, ढांचे के विभिन्न कार्यान्वयन पर एक जैसी अभिव्यक्ति के पेड़ में परिणाम की (जब तक रूपांतरण मानकीकृत है) है:

Expression<Func<int, int, int>> add = (int x, int y) => x + y; 

निम्नलिखित अंश C# Language Specification 4.0 (सभी मामलों में जोर दिया गया) से लिया जाता है।

सामान्य प्रकार Expression<D> के साथ ही एक अभिव्यक्ति पेड़ का निर्माण एक गुमनाम समारोह एक अभिव्यक्ति पेड़ प्रकार में बदल जाती है जब के लिए सटीक नियमों की सटीक परिभाषा, :

"4.6 अभिव्यक्ति पेड़ प्रकार" से

इस विनिर्देश के दायरे से बाहर हैं, और कहीं और वर्णित हैं।

से "अभिव्यक्ति पेड़ प्रकार के लिए अनाम समारोह रूपांतरणों की 6.5.2 मूल्यांकन": एक अभिव्यक्ति पेड़ प्रकार को एक गुमनाम समारोह के

रूपांतरण एक अभिव्यक्ति पेड़ का उत्पादन (§4.6)। अधिक सटीक रूप से, अज्ञात फ़ंक्शन रूपांतरण का मूल्यांकन किसी ऑब्जेक्ट संरचना के निर्माण की ओर जाता है जो अज्ञात फ़ंक्शन की संरचना का प्रतिनिधित्व करता है। अभिव्यक्ति वृक्ष की सटीक संरचना, साथ ही इसे बनाने के लिए सटीक प्रक्रिया, क्रियान्वयन परिभाषित हैं।

"6.5.3 कार्यान्वयन उदाहरण" में तीसरा उदाहरण को उस अज्ञात फ़ंक्शन एक स्थानीय चर कब्जा के रूपांतरण को दर्शाता है, और इस बात की पुष्टि चर पदोन्नति मेरे सवाल में उल्लेख किया है:

के जीवनकाल स्थानीय चर को अब कम से कम गुमनाम फ़ंक्शन प्रतिनिधि के जीवनकाल तक बढ़ाया जाना चाहिए। यह स्थानीय चर को एक कंपाइलर जेनरेट कक्षा के क्षेत्र में "hoisting" द्वारा हासिल किया जा सकता है। स्थानीय चर (§7.15.5.2) का इंस्टेंटेशन तब संकलक जेनरेट क्लास का एक उदाहरण बनाने के अनुरूप है, और स्थानीय वैरिएबल तक पहुंचने के लिए कंपाइलर जेनरेट क्लास के उदाहरण में फ़ील्ड तक पहुंचने के अनुरूप है।

यह आगे अनुभाग के अंत में इसकी पुष्टि की है:

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

कार्यान्वयन यहाँ वर्णित माइक्रोसॉफ्ट सी # संकलक द्वारा इस्तेमाल किया एक ही सिद्धांतों पर आधारित है, लेकिन यह द्वारा कोई एक साधन है:

हालांकि, वहाँ खंड की शुरुआत में एक अस्वीकरण है अनिवार्य कार्यान्वयन, न ही यह केवल एक ही संभव है। यह केवल संक्षेप में अभिव्यक्ति पेड़ में रूपांतरण का उल्लेख करता है, क्योंकि उनके सटीक अर्थशास्त्र इस विनिर्देश के दायरे से बाहर हैं।

पीएस एरिक लिपर्ट confirms in this comment कि अभिव्यक्ति वृक्ष चश्मे कभी नहीं भेजे गए थे। कोडप्लेक्स पर डीएलआर दस्तावेज के तहत Expression Trees v2 Spec मौजूद है, लेकिन इसका दायरा गुमनाम कार्यों के रूपांतरण को सी # में अभिव्यक्ति पेड़ों में शामिल करने के लिए प्रकट नहीं होता है।

+0

@ रैली25rs: अच्छा बिंदु। मेरी धारणा यह है कि माइक्रोसॉफ्ट * के पास एक आंतरिक कल्पना है जिसे वे अपने सभी कार्यान्वयन के लिए पालन करते हैं, लेकिन उन्होंने इसे सार्वजनिक रूप से मानकीकृत करने के लिए प्रतिबद्ध नहीं किया है। मतलब यह मानना ​​लगभग निश्चित रूप से सुरक्षित है कि फ्रेमवर्क के अन्य हिस्सों (जैसे कि लिंक 2 एसक्यूएल) पर निर्भर रूपांतरण लगातार बने रहेंगे; हालांकि, यह आश्वासन सामान्य रूप से अभिव्यक्तियों तक विस्तारित नहीं होता है (जैसे पैरामीटर नाम पढ़ने के लिए मेरे प्रश्न में उल्लिखित अभिव्यक्ति)। – Douglas

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