2010-12-02 7 views
5

Ben ifade ağaçlar ayrıştırma ile deniyorum ve aşağıdaki kodu yazdım: kodunC#: String parametresi gizemli şekilde sıfırlanacak şekilde sıfırlandı - lütfen yardım edin!

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(); 
    } 

fikri ifade ağacı ayrıştırmak ve dize değişkeni çıkışı içine düğümler ilgili ayrıntıları yazmak. Ancak, bu değişken sayfaya yazıldığında (Output() yöntemini kullanarak), boş olduğunu buluyorum. Kod boyunca adım hata ayıklayıcı kullandığınızda

, I çıkışı doğru kod ilk kez HandleParameterExpression() yürütüldüğünde x 'olarak ayarlanır, ancak bulmak en kısa sürede HandleParameterExpression() geri anahtar bloğunda kontrol döner HandleExpression(), değişken tekrar gizemli bir şekilde boş.

Dizgiler başvuru türleri olduğundan, yöntemleri referanslar arasında geçiş yapabilmem ve yöntemler tarafından yapılan değere yapılan değişiklikler korunmalıdır, doğru mu? Farkında olmadığım C# 'da geçen bazı parametre parametreleri var mı?

+0

Kolay kaplanlar! Beş dakikada dört cevap! Herkese büyük teşekkür! – David

+0

Neden değiştirilen çıktıyı geri vermiyorsunuz? Bir şey mi eksik? –

+0

@Omar: çünkü ihtiyacım yok. Parametrelerin değiştirilmesinin yanı sıra bir şeylerin döndürülmesi için de yöntemler kullanmak mümkündür. – David

cevap

6

Aslında referans olarak değiştirmek istediğiniz ANY değişkenini iletmeniz gerekir.

private void HandleOrElseExpression(Expression expression, ref string output) 

Ve işlevini çağırdığınızda o zaman, bu şekilde yapardı: Yani, örnekte, bu şekilde yapmak gerekir

HandleOrElseExpression(expression, ref output) 
+0

Yani bir sınıf örneğini, durumunu değiştirmeyi amaçlayan bir yönteme aktarırsam, açıkça başvurmak zorundayım! Yemin ederim ki hiçbir zaman referans olarak hiç bir şey geçmedim ve bu problemi daha önce hiç yaşamadım ... – David

+1

Eğer bir nesneyi geçiriyorsanız ve üzerinde özellikleri ayarlıyorsanız ya da metodları çağırıyorsanız o zaman referans ile geçmek için. Fakat bu nesneyi başka bir örneği olarak ayarlamak isterseniz (myObject = new Object() ifadesini yazmak gibi), yeni olanı kullanmak için referans ile (veya Botz3000 olarak belirtilen bir çıkış parametresi olarak) geçmeniz gerekir. Fonksiyonun dışında bir değer –

+0

@David: Hayır, bir * nesnesinin durumunu değiştiriyorsanız *, referans ile geçmek zorunda değilsiniz. –

8

dizesindeki numaralı veriyi hiçbir zaman değiştiremezsiniz, çünkü bu değişmezdir.

sahip her zamanı:

output += something; 

söylüyor:

output = output + something; 

"çıkışı + şey" nin değeri aslında String.Concat(output, something) arayarak sonucudur - Yeni bir dizeye yani bir referans. Bu nedenle, kodunuz yeni dizeye başvurmak için değişkenininoutput10 değerini değiştiriyor. Varolan dizedeki veriler değişmeden kalır. Parametre referans ile bu geçirilir sürece

bir parametre değerinin değiştirilmesi (ref veya out kullanarak) olup değişim arayan karşılık gelen değer olacak. Daha fazla bilgi için benim article on parameter passing'a bakın. Bir referansı değer olarak geçirme ile bir değişkeni referans olarak geçirme arasındaki farkı not edin.

Bunun yerine kodunuzu StringBuilder kullanmak için değiştirmenizi öneririm. private void HandleExpression(Expression expression, out string output) değiştirin private void HandleExpression(Expression expression, string output) ve HandleExpression(expression.Body, out output); Sonra işlevine iletilen argüman etkileyecektir yöntemde output yazılı olan HandleExpression(expression.Body, output); değiştirin:

Örnek: out params kullanmak istediğiniz gibi

+0

Her zaman referans türlerinin (ör. Dizeler) BY DEFAULT tarafından referans alınarak iletildiğini düşündüm. Adın ne anlama geldiğini düşündüm ... – David

+0

@David: Hayır, bu tür bir ifadenin değeri, verileri saklamak yerine verileri içeren bir nesneye yapılan bir başvurudır. Ayrıntılar için makalemi oku. –

3

Dizeler değiştirilemez, bu nedenle output'a başka bir değer atayarak output değiştirmiyorsunuz, ancak yeni bir dize değişkeni oluşturuyorsunuz.

output parametresini ref olarak bildirmek isteyebilirsiniz.

İlgili konular