using System;
using System.Linq.Expressions;
class Program
{
static void Main()
{
Expression<Func<float, uint>> expr = x => (uint) x;
Func<float,uint> converter1 = expr.Compile();
Func<float,uint> converter2 = x => (uint) x;
var aa = converter1(float.MaxValue); // == 2147483648
var bb = converter2(float.MaxValue); // == 0
}
}
使用 Expression.Convert
进行以下类型转换编译时,可能会发现相同但不同的行为:
Single -> UInt32
Single -> UInt64
Double -> UInt32
Double -> UInt64
看起来很奇怪,是吗?
<=== 添加了一些我的研究 ===>
我查看了使用DynamicMethod Visualizer和一些反射技巧从编译的Expression<TDelegate>
获取DynamicMethod
的编译后MSIL代码:
Expression<Func<float, uint>> expr = x => (uint) x;
Func<float,uint> converter1 = expr.Compile();
Func<float,uint> converter2 = x => (uint) x;
// get RTDynamicMethod - compiled MethodInfo
var rtMethodInfo = converter1.Method.GetType();
// get the field with the reference
var ownerField = rtMethodInfo.GetField(
"m_owner", BindingFlags.NonPublic | BindingFlags.Instance);
// get the reference to the original DynamicMethod
var dynMethod = (DynamicMethod) ownerField.GetValue(converter1.Method);
// show me the MSIL
DynamicMethodVisualizer.Visualizer.Show(dynMethod);
我得到的是这段 MSIL 代码:
IL_0000: ldarg.1
IL_0001: conv.i4
IL_0002: ret
而等效的C#编译方法具有以下主体:
IL_0000: ldarg.0
IL_0001: conv.u4
IL_0002: ret
大家是否注意到ExpressionTrees为此转换编译的代码无效?
conv.u4
MSIL操作码外,不使用任何其他技术 =) - controlflow