Dav*_*vid 5 c# pass-by-reference expression-trees
我正在尝试解析表达式树并编写了以下代码:
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();
}
Run Code Online (Sandbox Code Playgroud)
代码的思想是解析表达式树并将有关节点的详细信息写入字符串变量输出.但是,当这个变量写入页面时(使用该Output()方法),我发现它是空的.
当我使用调试器逐步执行代码时,我发现当代码HandleParameterExpression()第一次执行时输出被正确设置为'x' ,但是一旦控件从HandleParameterExpression()返回到开关块返回HandleExpression(),变量就会神秘地为空再次.
由于字符串是引用类型,我应该只是能够在方法之间传递引用,并且应该保留对方法所做的值的修改,对吧?在C#中是否存在一些我不知道的参数传递的微妙之处?
你永远改变数据中的字符串,因为它是不可变的.
每次你有:
output += something;
Run Code Online (Sandbox Code Playgroud)
那是说:
output = output + something;
Run Code Online (Sandbox Code Playgroud)
"output + something"的值实际上是调用的结果String.Concat(output, something)- 即对新字符串的引用.所以你的代码正在改变变量 的值output来引用新的字符串.现有字符串中的数据保持不变.
更改参数的值不会更改调用者中的相应值,除非参数通过引用传递(使用ref或out).有关详细信息,请参阅有关参数传递的文章.注意通过值传递引用和通过引用传递变量之间的区别.
我建议你改用你的代码来StringBuilder代替.
您需要传入要通过引用实际更改的任何变量.因此,在您的示例中,您需要这样做:
private void HandleOrElseExpression(Expression expression, ref string output)
Run Code Online (Sandbox Code Playgroud)
然后当你调用函数时,你会这样做:
HandleOrElseExpression(expression, ref output)
Run Code Online (Sandbox Code Playgroud)