C#:字符串参数被神秘地重置为空 - 请帮忙!

发布于 2024-10-05 10:33:04 字数 2529 浏览 8 评论 0原文

我正在尝试解析表达式树并编写了以下代码:

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() 时,输出被正确设置为“x”,但一旦控制从 返回>HandleParameterExpression() 回到 HandleExpression() 中的 switch 块,变量又神秘地为空。

由于字符串是引用类型,因此我应该能够在方法之间传递引用,并且应该保留方法对其值所做的更改,对吧? C# 中参数传递是否有一些我不知道的微妙之处?

I'm experimenting with parsing expression trees and have written the following code:

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

The idea of the code is to parse the expression tree and write details about the nodes into the string variable output. However, when this variable is written to the page (using the Output() method), I'm finding it's empty.

When I use the debugger to step through the code, I find that output is correctly set to 'x' when the code executes HandleParameterExpression() for the first time, but as soon as control returns from HandleParameterExpression() back to the switch block in HandleExpression(), the variable is mysteriously empty again.

Since strings are reference types, I should simply be able to pass the reference between the methods and changes to its value made by the methods should be retained, right? Is there some subtlety of parameter passing in C# that I'm not aware of?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

勿挽旧人 2024-10-12 10:33:05

看起来您想使用 out 参数:

示例:将 private void HandleExpression(Expression expression, string output) 更改为 private void HandleExpression(Expression expression, out string output) ) 并将 HandleExpression(expression.Body, output); 替换为 HandleExpression(expression.Body, out output);
然后在方法中写入output将会影响传递给函数的参数。

Looks like you want to use out params:

Example: Change private void HandleExpression(Expression expression, string output) to private void HandleExpression(Expression expression, out string output) and replace HandleExpression(expression.Body, output); with HandleExpression(expression.Body, out output);
Then writing to output in the method will affect the argument passed to the function.

月隐月明月朦胧 2024-10-12 10:33:04

您永远不会更改字符串内的数据,因为它是不可变的。

每次你有:

output += something;

这就是说:

output = output + something;

“output + Something”的值实际上是调用String.Concat(output, Something)的结果 - 即对新字符串的引用。因此,您的代码正在更改变量 output 的值以引用新字符串。现有字符串中的数据保持不变。

更改参数的值不会更改调用者中的相应值,除非该参数通过引用传递(使用refout )。有关更多详细信息,请参阅我的有关参数传递的文章。请注意按值传递引用和按引用传递变量之间的区别。

我建议您更改代码以使用 StringBuilder 代替。

You're never changing the data within the string, because it's immutable.

Each time you have:

output += something;

that's saying:

output = output + something;

The value of "output + something" is actually the result of calling String.Concat(output, something) - i.e. a reference to a new string. So your code is changing the value of the variable output to refer to the new string. The data in the existing string remains unchanged.

Changing the value of a parameter won't change the corresponding value in the caller, unless the parameter is passed by reference (using ref or out). See my article on parameter passing for more details. Note the difference between passing a reference by value, and passing a variable by reference.

I suggest you change your code to use StringBuilder instead.

你爱我像她 2024-10-12 10:33:04

您需要传入您想要通过引用实际更改的任何变量。因此,在您的示例中,您需要这样做:

private void HandleOrElseExpression(Expression expression, ref string output)

然后当您调用该函数时,您需要这样做:

HandleOrElseExpression(expression, ref output)

You need to pass in ANY variable that you want to actually change by reference. So, in your example, you would need to do it this way:

private void HandleOrElseExpression(Expression expression, ref string output)

And then when you call the function, you would do it this way:

HandleOrElseExpression(expression, ref output)
冬天旳寂寞 2024-10-12 10:33:04

字符串是不可变的,因此通过为 output 分配另一个值,您不会更改 output,而是创建一个新的字符串变量。

您可能希望将 output 参数声明为 ref

Strings are immutable, so by assigning another value to output, you are not changing output, but creating a new string variable.

You might want to declare the output parameter as ref.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文