"Бинарный оператор 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"
в специальном синтаксическом саже С#, что компилятор выражения не имеет доступа к?
Ответы
Ответ 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()());
Будет выводиться:
привет мир