Не могу инициализировать LambdaExpression с выражением - PullRequest
2 голосов
/ 11 августа 2011

Вопрос похож на один от Джона К , но более конкретный и принятый ответ не соответствует моим потребностям.

Это прекрасно компилируется:

Expression<Func<object, object>> specificExpression = (object o) => new object();
Expression generalExpression = specificExpression;

А этот нет:

Expression generalExpression = (object o) => new object();

Сообщенная ошибка компиляции:

Cannot convert lambda expression to type 'System.Linq.Expressions.Expression' because it is not a delegate type

Expression<Func<T1,T2>> происходит от Expression.

Теперь у меня есть фреймворк с методами, принимающими все виды выражений, то есть тип Expression. Вызывает разочарование принудительное приведение лямбда-выражений к соответствующему Expression<Func<T1,T2>> при каждом вызове метода.

Какие-либо веские причины, почему это основное поведение ООП нарушается в этом случае?

Ответы [ 3 ]

8 голосов
/ 11 августа 2011

Преобразование не работает, потому что компилятор не может определить, какой именно тип выражения вы пытаетесь создать. Что если ты сделал это?

Expression generalExpression = (object o) => "foo";

Должно ли это быть Expression<Func<object, string>>? А как насчет Expression<Func<object, object>> или Expression<Func<object, IComparable>>? Все эти типы будут допустимым конечным типом для дерева выражений, и компилятор не претендует на то, что знает, что вы пытаетесь сделать.

Вам необходимо привести конкретный тип, чтобы сообщить компилятору, какой тип выражения вы хотите создать:

Expression generalExpression = (Expression<Func<object, object>>)
    (object o) => new object();

Если вы попытаетесь это сделать, вы увидите похожую ошибку компилятора:

Delegate generalDelegate = delegate() { };

Является ли это Action, или ThreadStart, или каким-либо другим видом делегата без аргументов, возвращающего пустоту?

0 голосов
/ 11 августа 2011

Компилятор C # оценивает выражение в наименее сложную форму, например:

 var x = (object o) => new object();

x должно быть Func<object, object>, а не Expression<Func<object, object>>.В этом случае компилятор определяет, что значение является делегатом, и, поскольку Expression не может принимать делегат (только типы Expression<Func<>> / Expression<Action>), возникает ошибка компилятора.

Также см. Ответ @ Riana, потому что форма выражения фактически переписывается компилятором.

0 голосов
/ 11 августа 2011

Когда вы пишете

Expression<Func<object, object>> specificExpression = (object o) => new object();

На самом деле простота написания, которую нам предлагает компилятор C #.

Это выражение фактически будет скомпилировано во что-токак это:

Expression.Lambda<Func<object, object>> specificExpression = Expression.Lambda<Func<object,object>> ( ... )

и, как вы можете видеть, Expression<Func<object,object>> не является типом делегата, даже если первое выражение может привести нас к ошибке и позволит нам поверить, что это так.

«Выражение» не относится к типу делегата, поэтому вы не можете назначить его непосредственно объекту делегата, поскольку компилятор не предлагает простоты написания (как это делается для Expression<T> классов).

Извините, что говорю это, но вы должны идти разочаровывающим путем.

Риана

...