Expression.Convert
вообще бросается в InvalidOperationException
, когда "Не определен оператор преобразования между expression.Type и type."
Параметр возвращаемого типа Func
является ковариантным для ссылочных типов.
// This works.
Func a = () => new SomeType();
Func
Он не ковариантен для типов значений.
Вариативность применяется только к ссылочным типам; если вы указываете тип значения для параметра вариативного типа, то этот параметр типа инвариантен для результирующего построенного типа.
// This doesn't work!
Func five = () => 5;
Func
Однако Expression.Convert
считает, что это возможно.
Func answer = () => 42;
Expression answerExpression = Expression.Constant( answer );
// No InvalidOperationException is thrown at this line.
Expression converted
= Expression.Convert( answerExpression, typeof( Func
При вызове InvalidOperationException
не возникает Expression.Convert
. Дерево выражений компилируется правильно, но когда я вызываю созданный делегат, я получаю ожидаемое InvalidCastException
.
Convert
. Я бы очень предпочел метод, который не должен использовать обработку исключений в качестве логики. Похоже, что вся логика дисперсии не поддерживается должным образом. Она правильно жалуется на невозможность преобразования из Func
в Func
, но не жалуется на преобразование из Func
в Func
.
Интересно, что если SomeType
и SomeOtherType
находятся в одной иерархии классов (SomeOtherType
extends from SomeType
), то исключение не возникает. Если это не так, то выбрасывает.