2010-12-02 10 views
5

मैं अभिव्यक्ति पेड़ पार्स करने के साथ प्रयोग कर रहा हूँ और निम्नलिखित कोड लिखा है:सी #: स्ट्रिंग पैरामीटर रहस्यमय रूप से खाली पर रीसेट किया जा रहा है - कृपया मदद करें!

private void TestExpressionTree() 
    { 
    Expression<Func<int, bool>> expression = x => x == 1 || x == 2; 
    string output = String.Empty; 
    HandleExpression(expression.Body, output); 
    Output("Output", output); 
    } 

    private void HandleExpression(Expression expression, string output) 
    { 
    switch (expression.NodeType) 
    { 
     case ExpressionType.Conditional: 
     HandleConditionalExpression(expression, output); 
     break; 
     case ExpressionType.OrElse: 
     HandleOrElseExpression(expression, output); 
     break; 
     case ExpressionType.Equal: 
     HandleEqualExpression(expression, output); 
     break; 
     case ExpressionType.Parameter: 
     HandleParameterExpression(expression, output); 
     break; 
     case ExpressionType.Constant: 
     HandleConstantExpression(expression, output); 
     break; 
    } 
    } 

    private void HandleConditionalExpression(Expression expression, string output) 
    { 
    ConditionalExpression conditionalExpression = (ConditionalExpression) expression; 
    HandleExpression(conditionalExpression.Test, output); 
    } 

    private void HandleOrElseExpression(Expression expression, string output) 
    { 
    BinaryExpression binaryExpression = (BinaryExpression)expression; 
    HandleExpression(binaryExpression.Left, output); 
    output += "||"; 
    HandleExpression(binaryExpression.Right, output); 
    } 

    private void HandleEqualExpression(Expression expression, string output) 
    { 
    BinaryExpression binaryExpression = (BinaryExpression)expression; 
    HandleExpression(binaryExpression.Left, output); 
    output += "="; 
    HandleExpression(binaryExpression.Right, output); 
    } 

    private void HandleParameterExpression(Expression expression, string output) 
    { 
    ParameterExpression parameterExpression = (ParameterExpression)expression; 
    output += parameterExpression.Name; 
    } 

    private void HandleConstantExpression(Expression expression, string output) 
    { 
    ConstantExpression constantExpression = (ConstantExpression)expression; 
    output += constantExpression.Value.ToString(); 
    } 

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

जब मैं डिबगर का उपयोग कोड से निकलने के लिए, मुझे लगता है कि उत्पादन सही ढंग से 'एक्स' के लिए निर्धारित है जब कोड पहली बार के लिए HandleParameterExpression() कार्यान्वित करता है, लेकिन जैसे ही नियंत्रण रिटर्न HandleParameterExpression() से पीठ में स्विच ब्लॉक करने के लिए HandleExpression(), चर रहस्यमय रूप से खाली है।

चूंकि तार संदर्भ प्रकार हैं, इसलिए मुझे विधियों के बीच संदर्भ को पारित करने में सक्षम होना चाहिए और विधियों द्वारा किए गए मूल्य में परिवर्तनों को बनाए रखा जाना चाहिए, है ना? क्या सी # में गुजरने वाले पैरामीटर की कुछ सूक्ष्मता है जिसे मुझे पता नहीं है?

+0

आसान बाघों! पांच मिनट में चार जवाब! सभी को भारी धन्यवाद! – David

+0

आप संशोधित आउटपुट क्यों नहीं लौट रहे हैं? क्या मैं कुछ भूल रहा हूँ? –

+0

@ ओमार: क्योंकि मुझे इसकी आवश्यकता नहीं है। मापदंडों को संशोधित करने के साथ-साथ बस कुछ लौटने के तरीकों का उपयोग करना संभव है। – David

उत्तर

6

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

private void HandleOrElseExpression(Expression expression, ref string output) 

और फिर जब आप फ़ंक्शन को कॉल करें, तो आप इसे इस तरह से करना होगा:

HandleOrElseExpression(expression, ref output) 
+0

इसलिए यदि मैं एक वर्ग उदाहरण में एक विधि में पास करता हूं जिसका उद्देश्य अपने राज्य को बदलने का इरादा है, तो मुझे स्पष्ट रूप से संदर्भ द्वारा पारित करने की आवश्यकता है! मैं कसम खाता हूं कि मैंने कभी भी संदर्भ से कुछ भी पारित नहीं किया है, और मुझे पहले कभी यह समस्या नहीं मिली है ... – David

+1

यदि आप किसी ऑब्जेक्ट में गुजर रहे हैं और उस पर गुण सेट कर रहे हैं या उस पर विधियों को कॉल कर रहे हैं, तो नहीं, आपको इसकी आवश्यकता नहीं है संदर्भ द्वारा इसे पारित करने के लिए। लेकिन अगर आप उस ऑब्जेक्ट को इसके दूसरे उदाहरण के रूप में सेट करना चाहते हैं (जैसे myObject = new ऑब्जेक्ट() कह रहे हैं, तो आपको इसे संदर्भित करने के लिए संदर्भ (या आउटपुट पैरामीटर के रूप में, बोटज़ 3000 के रूप में) को पास करने की आवश्यकता है फ़ंक्शन के बाहर मान –

+0

@ डेविड: नहीं, यदि आप * ऑब्जेक्ट * की स्थिति बदल रहे हैं, तो आपको संदर्भ से गुजरने की आवश्यकता नहीं है। ऐसा है कि आप बदलने की कोशिश कर रहे हैं * एक ऑब्जेक्ट को ऑब्जेक्ट करने के लिए * कि आप 'ref' का उपयोग करना चाहते हैं। –

8

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

हर बार जब आप है:

output += something; 

कि कहावत है:

output = output + something; 

"आउटपुट + कुछ" का मूल्य वास्तव में String.Concat(output, something) बुला का परिणाम है - यानी एक नया स्ट्रिंग के लिए एक संदर्भ। तो आपका कोड नई स्ट्रिंग को संदर्भित करने के लिए परिवर्तनीयoutput के मान को बदल रहा है। मौजूदा स्ट्रिंग में डेटा अपरिवर्तित बनी हुई है।

एक पैरामीटर के मान में बदलाव नहीं परिवर्तन कॉलर में संबंधित मान, जब तक पैरामीटर संदर्भ द्वारा पारित कर दिया है (ref या out का प्रयोग करके) होगा। अधिक जानकारी के लिए मेरे article on parameter passing देखें। मान द्वारा संदर्भ पारित करने और संदर्भ द्वारा एक चर पारित करने के बीच अंतर ध्यान दें।

मेरा सुझाव है कि आप इसके बजाय StringBuilder का उपयोग करने के लिए अपना कोड बदल दें।

+0

मैंने हमेशा सोचा कि संदर्भ प्रकार (उदा। तार) संदर्भ द्वारा संदर्भ द्वारा पारित किए गए थे। मैंने सोचा था कि नाम क्या था ... – David

+0

@ डेविड: नहीं, इसका मतलब है कि उस प्रकार की अभिव्यक्ति का मूल्य डेटा को रखने के बजाए डेटा युक्त किसी ऑब्जेक्ट का संदर्भ है। विवरण के लिए मेरा लेख पढ़ें। –

1

ऐसा लगता है कि out पैरामीटर का उपयोग करना चाहते: private void HandleExpression(Expression expression, out string output) को बदलें private void HandleExpression(Expression expression, string output) और HandleExpression(expression.Body, out output); तो विधि तर्क समारोह के लिए पारित प्रभावित करेगा में output के लिए लिख साथ HandleExpression(expression.Body, output); बदल देते हैं:

उदाहरण।

3

स्ट्रिंग्स अपरिवर्तनीय हैं, इसलिए output पर एक और मान असाइन करके, आप output बदल नहीं रहे हैं, लेकिन एक नया स्ट्रिंग चर बना रहे हैं।

आप पैरामीटर ref के रूप में घोषित करना चाहते हैं।

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