【问题标题】:"The binary operator Add is not defined for the types 'System.String' and 'System.String'." -- Really?“二元运算符 Add 没有为类型 'System.String' 和 'System.String' 定义。” - 真的?
【发布时间】:2011-08-11 14:09:59
【问题描述】:

尝试运行以下代码时:

    Expression<Func<string, string>> stringExpression = Expression.Lambda<Func<string, string>>(
        Expression.Add(
            stringParam,
            Expression.Constant("A")
        ),
        new List<ParameterExpression>() { stringParam }
    );

    string AB = stringExpression.Compile()("B");

我收到标题中引用的错误:“二元运算符 Add 没有为类型 'System.String' 和 'System.String' 定义。”真的是这样吗?显然在 C# 中它可以工作。是否在表达式编译器无法访问的 C# 特殊语法糖中做 string s = "A" + "B"

【问题讨论】:

  • 后续我猜:为什么表达式编译器没有像 C# 编译器一样神奇?
  • 回答后续,为什么要呢?虽然有些语言使用+ 作为连接运算符以及数字类型的加法运算符,但这并不通用(其他常见的连接运算符包括.||&amp;&lt;&lt;)甚至那些使用+ 的人在这种情况下也将其称为concatenationExpression.Add 方法被称为 Add 并且人们可以期望它做加法而不做任何其他事情(除非一个类型已经重载了 + 但是因为它在内部是一个名为 op_addition 的方法,该类型声称它是添加)。

标签: c# expression-trees


【解决方案1】:

完全正确,是的。没有这样的运算符 - C# 编译器将string + string 转换为对string.Concat 的调用。 (这很重要,因为这意味着x + y + z 可以转换为string.Concat(x, y, z),从而避免了无意义地创建中间字符串。

查看 string operators 的文档 - 只有 ==!= 由框架定义。

【讨论】:

    【解决方案2】:

    这也引起了我的注意,正如 Jon 在他的回答中指出的那样,C# 编译器将 string + string 转换为 string.Concat。有一个overload of the Expression.Add method 允许您指定要使用的“添加”方法。

    var concatMethod = typeof(string).GetMethod("Concat", new[] { typeof(string), typeof(string) }); 
    var addExpr = Expression.Add(Expression.Constant("hello "),Expression.Constant("world"), concatMethod);
    

    您可能想要更改string.Concat 方法以使用正确的overload

    证明这是可行的:

    Console.WriteLine(Expression.Lambda<Func<string>>(addExpr).Compile()());
    

    将输出:

    你好世界

    【讨论】:

      【解决方案3】:

      是的,这是一个惊喜不是吗!!!编译器将其替换为对 String.Concat 的调用。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-07-20
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-12-07
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多