Expression.Convert不会为不变值类型参数抛出InvalidOperationException?

Ste*_*ris 5 c# covariance contravariance expression-trees

Expression.Convert通常在"expression.Type和type之间定义了无转换运算符"InvalidOperationException时抛出.

返回类型参数Func<>是参考类型的协变.

// This works.
Func<SomeType> a = () => new SomeType();
Func<object> b = a;
Run Code Online (Sandbox Code Playgroud)

对于值类型不是协变的.

差异仅适用于参考类型; 如果为变量类型参数指定值类型,则该类型参数对于生成的构造类型是不变的.

// This doesn't work!
Func<int> five = () => 5;
Func<object> fiveCovariant = five;
Run Code Online (Sandbox Code Playgroud)

但是,Expression.Convert相信它是可能的.

Func<int> answer = () => 42;
Expression answerExpression = Expression.Constant( answer );
// No InvalidOperationException is thrown at this line.
Expression converted 
    = Expression.Convert( answerExpression, typeof( Func<object> ) );
Run Code Online (Sandbox Code Playgroud)

InvalidOperationException呼叫时不会抛出Expression.Convert.表达式树正确编译,但是当我调用创建的委托时,我得到了预期的结果InvalidCastException.

  1. 这是一个错误吗?(我将其报告为Microsoft Connect上的错误.)
  2. 如何正确检查一个类型是否可以转换为另一种类型?一些答案似乎指的是使用Convert.我非常喜欢一种不必将异常处理用作逻辑的方法.

似乎没有正确支持整个方差逻辑.它正确地抱怨无法转换Func<SomeType>Func<SomeOtherType>,但它并没有抱怨转换Func<object>Func<string>.

有趣的是,一旦SomeType并且SomeOtherType处于相同的类层次结构(SomeOtherType从中扩展SomeType),它就不会抛出异常.如果他们不是,那就是.

Eri*_*ert 7

这是一个错误吗?

是.当我们添加协方差和逆变时,表达式树库可能不会始终更新.对于那个很抱歉.

我将其报告为Microsoft Connect上的错误.

谢谢!有人会看看它.

如何正确检查一个类型是否可以转换为另一种类型?

问题很模糊.给定两个类型对象,您想知道:

  • .NET运行时是否认为类型是赋值兼容的?
  • C#编译器是否认为类型之间存在隐式转换?
  • C#编译器是否认为类型之间存在显式转换?

例如,"int"和"short"与.NET规则不兼容.Int是可显式转换但不能隐式转换为short,而short可以通过C#规则隐式和显式转换为int.