C# &引用;CLR检测到一个无效的程序;将Enumerable.ToDictionary与扩展方法一起使用时
一位同事向我传递了一个有趣的代码示例,该示例在运行时因C# &引用;CLR检测到一个无效的程序;将Enumerable.ToDictionary与扩展方法一起使用时,c#,linq,clr,extension-methods,C#,Linq,Clr,Extension Methods,一位同事向我传递了一个有趣的代码示例,该示例在运行时因invalidProgrameException(“CLR检测到一个无效程序”)而崩溃 这个问题似乎发生在JIT时间,因为它编译得很好,但在调用带有“冒犯”行的方法之前抛出异常——我猜是因为它是JIT的 该行正在调用Enumerable.ToDictionary,并传入一个Func作为第二个参数 如果Func参数使用lambda完全指定,则该参数有效;如果将其指定为方法组,则if失败。这两者肯定是等价的吗 这让我(以及发现它的同事)感到困惑—
invalidProgrameException
(“CLR检测到一个无效程序”)而崩溃
这个问题似乎发生在JIT时间,因为它编译得很好,但在调用带有“冒犯”行的方法之前抛出异常——我猜是因为它是JIT的
该行正在调用Enumerable.ToDictionary
,并传入一个Func
作为第二个参数
如果Func
参数使用lambda完全指定,则该参数有效;如果将其指定为方法组,则if失败。这两者肯定是等价的吗
这让我(以及发现它的同事)感到困惑——而且这看起来确实像是一个JIT错误
[编辑:抱歉-我在代码示例中得到了错误的通过和失败案例-现在已更正(上面的描述是正确的)]
有人有解释吗
using System;
using System.Linq;
internal class Program
{
private static void Main(string[] args)
{
Test.Try();
}
}
public class Test
{
public static readonly int[] integers = new[] { 1, 3, 5 };
public static void Try()
{
var line = new Line { A = 3, B = 5 };
// PASSES
var dict = integers.ToDictionary<int, int, decimal>(i => i, i => line.Compute(i));
// FAILS
//var dict = integers.ToDictionary<int, int, decimal>(i => i, line.Compute);
Console.WriteLine(string.Join(" ", dict.Select(kv => kv.Key + "-" + kv.Value)));
}
}
public class Line
{
public decimal A;
public decimal B;
}
public static class SimpleCompute
{
public static decimal Compute(this Line line, int value)
{
return line.A*value + line.B;
}
}
使用系统;
使用System.Linq;
内部课程计划
{
私有静态void Main(字符串[]args)
{
Test.Try();
}
}
公开课考试
{
公共静态只读int[]整数=新[]{1,3,5};
公共静态void Try()
{
变量行=新行{A=3,B=5};
//通行证
var dict=integers.ToDictionary(i=>i,i=>line.Compute(i));
//失败
//var dict=integers.ToDictionary(i=>i,line.Compute);
Console.WriteLine(string.Join(“,dict.Select(kv=>kv.Key+”-“+kv.Value));
}
}
公共班级线
{
公共十进制A;
公共十进制B;
}
公共静态类SimpleComputer
{
公共静态十进制计算(此行,int值)
{
返回行.A*值+行.B;
}
}
编译器错误
关于信息,我有异步CTP,这可能是相关的<代码>csc报告:4.0.30319.440
似乎是以下两者之间的区别:
public static void TryTwo() // fails
{
var line = new Line {A = 3, B = 5};
var dict = integers.ToDictionary<int, int, decimal>(i => i, line.Compute);
Console.WriteLine("TryTwo complete");
}
public static void TryFive() // works
{
var line = new Line { A = 3, B = 5 };
Func<int, decimal> func = line.Compute;
var dict = integers.ToDictionary<int, int, decimal>(i => i, func);
Console.WriteLine("TryFour complete");
}
public static void TryTwo()//失败
{
变量行=新行{A=3,B=5};
var dict=integers.ToDictionary(i=>i,line.Compute);
Console.WriteLine(“TryTwo complete”);
}
public static void TryFive()//有效
{
变量行=新行{A=3,B=5};
Func Func=line.Compute;
var dict=整数。ToDictionary(i=>i,func);
Console.WriteLine(“尝试四次完成”);
}
让我们看看反射器:
.method public hidebysig static void TryTwo() cil managed
{
.maxstack 4
.locals init (
[0] class Line <>g__initLocal6)
L_0000: newobj instance void Line::.ctor()
L_0005: stloc.0
L_0006: ldloc.0
L_0007: ldc.i4.3
L_0008: newobj instance void [mscorlib]System.Decimal::.ctor(int32)
L_000d: stfld valuetype [mscorlib]System.Decimal Line::A
L_0012: ldloc.0
L_0013: ldc.i4.5
L_0014: newobj instance void [mscorlib]System.Decimal::.ctor(int32)
L_0019: stfld valuetype [mscorlib]System.Decimal Line::B
L_001e: ldsfld int32[] Test::integers
L_0023: ldsfld class [mscorlib]System.Func`2<int32, int32> Test::CS$<>9__CachedAnonymousMethodDelegate8
L_0028: brtrue.s L_003b
L_002a: ldnull
L_002b: ldftn int32 Test::<TryTwo>b__7(int32)
L_0031: newobj instance void [mscorlib]System.Func`2<int32, int32>::.ctor(object, native int)
L_0036: stsfld class [mscorlib]System.Func`2<int32, int32> Test::CS$<>9__CachedAnonymousMethodDelegate8
L_003b: ldsfld class [mscorlib]System.Func`2<int32, int32> Test::CS$<>9__CachedAnonymousMethodDelegate8
L_0040: call class [mscorlib]System.Collections.Generic.Dictionary`2<!!1, !!2> [System.Core]System.Linq.Enumerable::ToDictionary<int32, int32, valuetype [mscorlib]System.Decimal>(class [mscorlib]System.Collections.Generic.IEnumerable`1<!!0>, class [mscorlib]System.Func`2<!!0, !!1>, class [mscorlib]System.Func`2<!!0, !!2>)
L_0045: pop
L_0046: ldstr "TryTwo complete"
L_004b: call void [mscorlib]System.Console::WriteLine(string)
L_0050: ret
}
.method public hidebysing static void TryTwo()cil managed
{
.maxstack 4
.init(
[0]类行g_uuinitlocal6)
L_0000:newobj实例无效行::.ctor()
L_0005:stloc.0
L_0006:ldloc.0
L_0007:ldc.i4.3
L_0008:newobj实例void[mscorlib]System.Decimal::.ctor(int32)
L_000d:stfld valuetype[mscorlib]System.Decimal Line::A
L_0012:ldloc.0
L_0013:ldc.i4.5
L_0014:newobj实例void[mscorlib]System.Decimal::.ctor(int32)
L_0019:stfld valuetype[mscorlib]System.Decimal Line::B
L_001e:ldsfld int32[]测试::整数
L_0023:ldsfld类[mscorlib]System.Func`2测试::CS$9_ucachedanonymousmethoddelegate8
L_0028:brtrue.s L_003b
L_002a:ldnull
L_002b:ldftn int32测试::b__7(int32)
L_0031:newobj实例void[mscorlib]System.Func`2::.ctor(对象,本机int)
L_0036:stsfld类[mscorlib]System.Func`2测试::CS$9_ucachedanonymousmethoddelegate8
L_003b:ldsfld类[mscorlib]System.Func`2测试::CS$9_ucachedanonymousmethoddelegate8
L_0040:调用类[mscorlib]System.Collections.Generic.Dictionary`2[System.Core]System.Linq.Enumerable::ToDictionary(类[mscorlib]System.Collections.Generic.IEnumerable`1,类[mscorlib]System.Func`2,类[mscorlib]System.Func`2)
L_0045:流行音乐
L_0046:ldstr“完成两次尝试”
L_004b:调用void[mscorlib]System.Console::WriteLine(字符串)
L_0050:ret
}
vs
.method public hidebysing static void TryFive()cil managed
{
.maxstack 4
.init(
[0]类行,
[1] 类[mscorlib]System.Func`2 Func,
[2] 类行g__initLocal9)
L_0000:newobj实例无效行::.ctor()
L_0005:stloc.2
L_0006:ldloc.2
L_0007:ldc.i4.3
L_0008:newobj实例void[mscorlib]System.Decimal::.ctor(int32)
L_000d:stfld valuetype[mscorlib]System.Decimal Line::A
L_0012:ldloc.2
L_0013:ldc.i4.5
L_0014:newobj实例void[mscorlib]System.Decimal::.ctor(int32)
L_0019:stfld valuetype[mscorlib]System.Decimal Line::B
L_001e:ldloc.2
L_001f:stloc.0
L_0020:ldloc.0
L_0021:ldftn valuetype[mscorlib]System.Decimal simplecomputer::Compute(类行,int32)
L_0027:newobj实例void[mscorlib]System.Func`2::.ctor(对象,本机int)
L_002c:stloc.1
L_002d:ldsfld int32[]测试::整数
L_0032:ldsfld类[mscorlib]System.Func`2测试::CS$9_ucachedanonymousmethoddelegateb
L_0037:brtrue.s L_004a
L_0039:ldnull
L_003a:ldftn int32测试::b__a(int32)
L_0040:newobj实例void[mscorlib]System.Func`2::.ctor(对象,本机int)
L_0045:stsfld类[mscorlib]System.Func`2测试::CS$9_CachedAnonymousMethodDelegateb
L_004a:ldsfld类[mscorlib]System.Func`2测试::CS$9_CachedAnonymousMethodDelegateb
L_004f:ldloc.1
L_0050:调用类[mscorlib]System.Collections.Generic.Dictionary`2[System.Core]System.Linq.Enumerable::ToDictionary(类[mscorlib]System.Collections.Generic.IEnumerable`1,类[mscorlib]System.Func`2,类[mscorlib]System.Func`2)
L_0055:流行音乐
L_0056:ldstr“尝试四次完成”
L_005b:调用void[mscorlib]System.Console::WriteLine(字符串)
L_0060:ret
}
如果查看损坏的版本,它只加载一个代理。编译器错误,基本上:
L_0023: ldsfld class [mscorlib]System.Func`2<int32, int32> Test::CS$<>9__CachedAnonymousMethodDelegate8
L_0028: brtrue.s L_003b
L_002a: ldnull
L_002b: ldftn int32 Test::<TryTwo>b__7(int32)
L_0031: newobj instance void [mscorlib]System.Func`2<int32, int32>::.ctor(object, native int)
L_0036: stsfld class [mscorlib]System.Func`2<int32, int32> Test::CS$<>9__CachedAnonymousMethodDelegate8
L_003b: ldsfld class [mscorlib]System.Func`2<int32, int32> Test::CS$<>9__CachedAnonymousMethodDelegate8
L_0040: call class [mscorlib]System.Collections.Generic.Dictionary`2<!!1, !!2> [System.Core]System.Linq.Enumerable::ToDictionary<int32, int32, valuetype [mscorlib]System.Decimal>(class [mscorlib]System.Collections.Generic.IEnumerable`1<!!0>, class [mscorlib]System.Func`2<!!0, !!1>, class [mscorlib]System.Func`2<!!0, !!2>)
L_0023:ldsfld类[mscorlib]System.Func`2测试::CS$9_ucachedanonymousmethoddelegate8
L_0028:brtrue.s L_003b
L_002a:ldnull
L_002b:ldftn int32测试::b__7(
L_0023: ldsfld class [mscorlib]System.Func`2<int32, int32> Test::CS$<>9__CachedAnonymousMethodDelegate8
L_0028: brtrue.s L_003b
L_002a: ldnull
L_002b: ldftn int32 Test::<TryTwo>b__7(int32)
L_0031: newobj instance void [mscorlib]System.Func`2<int32, int32>::.ctor(object, native int)
L_0036: stsfld class [mscorlib]System.Func`2<int32, int32> Test::CS$<>9__CachedAnonymousMethodDelegate8
L_003b: ldsfld class [mscorlib]System.Func`2<int32, int32> Test::CS$<>9__CachedAnonymousMethodDelegate8
L_0040: call class [mscorlib]System.Collections.Generic.Dictionary`2<!!1, !!2> [System.Core]System.Linq.Enumerable::ToDictionary<int32, int32, valuetype [mscorlib]System.Decimal>(class [mscorlib]System.Collections.Generic.IEnumerable`1<!!0>, class [mscorlib]System.Func`2<!!0, !!1>, class [mscorlib]System.Func`2<!!0, !!2>)