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
}
}
Same unterschiedliches Verhalten gegründet werden kann, wenn Expression.Convert
für diese Umwandlungen Kompilieren:Ist das ein ExpressionTrees-Bug?
Single -> UInt32
Single -> UInt64
Double -> UInt32
Double -> UInt64
Sieht seltsam, nicht wahr?
< === einige meiner Forschung hinzugefügt ===>
ich bei der kompilierten DynamicMethod
MSIL Code sah bin mit DynamicMethod Visualizer und einige Überlegungen hacken DynamicMethod
von der kompilierten Expression<TDelegate>
zu erhalten:
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);
Und was ich bekommen, ist dies MSIL Code:
IL_0000: ldarg.1
IL_0001: conv.i4
IL_0002: ret
Und das gleich C# -compiled Methode hat diesen Körper:
IL_0000: ldarg.0
IL_0001: conv.u4
IL_0002: ret
jemand jetzt Sie sehen, dass ExpressionTrees für diese Umwandlung nicht gültig Code kompiliert?
Thx für Ihre Antwort, aber ja, es ist wichtig, dass das Überlaufverhalten anders ist! Was ist ein Grund dafür, dass die kompilierte Methode ein anderes Verhalten als normaler Code hat? – ControlFlow
C# verwendet keine anderen Techniken außer 'conv.u4' MSIL-Opcode zum Konvertieren von Gleitkommawerten in vorzeichenlose Ganzzahlen =) – ControlFlow