Expression.Convert
通常会引发InvalidOperationException
。
Func<>
的返回类型参数对于引用类型是协变的。
// This works.
Func<SomeType> a = () => new SomeType();
Func<object> b = a;
isn't covariant for value types。
差异仅适用于参考类型;如果为变量类型参数指定值类型,则该类型参数对于生成的构造类型是不变的。
// This doesn't work!
Func<int> five = () => 5;
Func<object> fiveCovariant = five;
但是,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> ) );
调用InvalidOperationException
时不会抛出Expression.Convert
。表达式树正确编译,但是当我调用创建的委托时,我得到了预期的InvalidCastException
。
Convert
。我非常喜欢一种不必将异常处理用作逻辑的方法。似乎没有正确支持整个方差逻辑。它正确地抱怨无法从Func<SomeType>
转换为Func<SomeOtherType>
,但它没有抱怨从Func<object>
转换为Func<string>
。
有趣的是,一旦SomeType
和SomeOtherType
位于同一个类层次结构中(SomeOtherType
从SomeType
扩展),它就不会抛出异常。如果不是,那就是。
答案 0 :(得分:7)
这是一个错误吗?
是。当我们添加协方差和逆变时,表达式树库可能不会始终更新。对不起。
我将其报告为Microsoft Connect上的错误。
谢谢!有人会看看它。
如何正确检查某种类型是否可以转换为其他类型?
问题很模糊。给定两个类型对象,您想知道:
答案 1 :(得分:1)
这不是一个错误。 Expression.Convert表示运行时类型检查,因此运行时的InvalidCastException将是预期的行为。
编辑:这不完全正确。它并不完全代表运行时类型检查(这是文档:http://msdn.microsoft.com/en-us/library/bb292051.aspx)。但是,表达式树是在运行时创建的,因此必须进行所有类型检查。
编辑:我也在使用.NET 4.0。
顺便说一下,Convert
并未抱怨从Func<object>
转换为Func<string>
,因为转换有时是合法的。如果Func<object>
是对运行时类型为Func<string>
的对象的协变引用,则是合法的。例如:
Func<string> sFunc = () => "S";
Func<object> oFunc = sFunc;
Func<string> anotherSFunc = (Func<string>)oFunc;
现在,Convert通过检查是否可以将一种类型强制转换为另一种类型来决定是否抛出InvalidOperationException。在检查委托进行潜在的引用转换时,看起来代码会检查逆变(参数)参数,如果有值类型则抛出InvalidOperationException
。它似乎没有检查协变(返回类型)参数。所以我开始怀疑这个是一个错误,虽然我倾向于保留对此的判断,直到我有机会查看规范(参见Eric Lippert的Maybe there's something wrong with the universe, but probably not),我现在没有时间做。
答案 2 :(得分:0)
如何正确检查某种类型是否可以转换为其他类型?
我只是首次尝试使用Type.CanConvertTo( Type to )
方法to my library。 (来源太复杂了,不能在这里发帖,抱歉。)
if ( fromType.CanConvertTo( toType ) )
{
convertedExpression = Expression.Convert( expression, toType );
}
到目前为止,它支持检查隐式转化:
它不支持:
通过all my tests for implicit conversions。虽然您也可以指定包含显式转换(我实际上是use it like that at the moment),但我仍然需要为所有这些场景编写单元测试。