Подтвердить что ты не робот

"Бинарный оператор Add не определен для типов" System.String "и" System.String "." -- В самом деле?

При попытке запустить следующий код:

    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 "." Это действительно так? Очевидно, что в С# это работает. Делает ли string s = "A" + "B" в специальном синтаксическом саже С#, что компилятор выражения не имеет доступа к?

4b9b3361

Ответ 1

Это абсолютно правильно, да. Такого оператора нет - компилятор С# преобразует string + string в вызов string.Concat. (Это важно, потому что это означает, что x + y + z можно преобразовать в string.Concat(x, y, z), что позволяет избежать создания промежуточных строк бессмысленно.

Посмотрите на документы для операторов строк - только рамки == и != определяются каркасом.

Ответ 2

Да, это сюрприз! Компилятор заменяет его вызовом String.Concat.

Ответ 3

Это тоже меня укусило, и, как указывает Джон в своем ответе, компилятор С# преобразует string + string в string.Concat. Существует перегрузка метода Expression.Add, который позволяет вам указать метод "добавить".

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

Возможно, вы захотите изменить метод string.Concat, чтобы использовать перегрузку .

Доказательство этого работает:

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

Будет выводиться:

привет мир