Tag: cil

LINQ如何编译成CIL?

例如: var query = from c in db.Cars select c; foreach(Car aCar in query) { Console.WriteLine(aCar.Name); } 一旦编译,这将如何翻译? 幕后发生了什么?

什么是(fnptr)*类型以及如何创建它?

以下IL代码创建名为(fnptr)*的Type实例(标记0x2000000 – 无效,模块mscorlib.dll)。 ldtoken method void* ()* call class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle) 这种类型的目的是什么? 是否可以在C#中创建此类型实例而无需编写任何IL代码,也许可以使用reflection? 令牌上的Module.ResolveType抛出ArgumentOutOfRangeException 。 编辑: 很明显, (fnptr)类型是IL方法指针类型的内部CLR类型表示,但是当删除最后一个* ,它只返回IntPtr 。 编辑#2: (fnptr)来自一个可以在SSCLI typestring.cpp中看到的函数 : // …or function pointer else if (ty.IsFnPtrType()) { // Don’t attempt to format this currently, it may trigger GC due to fixups. tnb.AddName(L”(fnptr)”); } 为什么基本的fnptr返回IntPtr可以在typehandle.cpp中看到: OBJECTREF TypeHandle::GetManagedClassObject() const { […] […]

DynamicMethod比编译的IL函数慢得多

我写了一个复制公共属性的简单对象复制器。 我无法弄清楚为什么Dynamic方法比c#版本慢得多。 持续时间 C#方法:4,963毫秒 动态方法:19,924毫秒 请注意 – 当我在启动秒表之前运行动态方法时 – 持续时间不包括编译阶段。 我在调试和发布模式下,在x86和x64模式下运行,从VS和命令行运行,结果大致相同(动态方法慢400%)。 const int NBRECORDS = 100 * 1000 * 1000; public class Person { private int mSomeNumber; public string FirstName { get; set; } public string LastName { get; set; } public DateTime DateOfBirth { get; set; } public int SomeNumber { get { return […]

动态创建方法并执行它

背景: 我想在C#中定义一些static方法,并从运行时(在客户端上)选择的这些方法之一生成IL代码作为字节数组,并通过网络将字节数组发送到应该执行它的另一台机器(服务器)从字节数组重新生成IL代码之后。 我的尝试: ( POC ) public static class Experiment { public static int Multiply(int a, int b) { Console.WriteLine(“Arguments ({0}, {1})”, a, b); return a * b; } } 然后我得到方法体的IL代码,如: BindingFlags flags = BindingFlags.Public | BindingFlags.Static; MethodInfo meth = typeof(Experiment).GetMethod(“Multiply”, flags); byte[] il = meth.GetMethodBody().GetILAsByteArray(); 到目前为止,我没有动态创建任何东西。 但我把IL代码作为字节数组,我想创建一个程序集,然后是一个模块,然后是一个类型,然后是一个方法 – 所有这些都是动态的。 在创建动态创建方法的方法体时,我使用上面代码中使用reflection得到的IL代码。 代码生成代码如下: AppDomain domain = […]

MS C#编译器和非优化代码

注意:我发现我发布的示例中有一些错误 – 编辑修复它 如果你不启用优化,官方的C#编译器会做一些有趣的事情。 例如,一个简单的if语句: int x; // … // if (x == 10) // do something 如果优化,会变成以下内容: ldloc.0 ldc.i4.s 10 ceq bne.un.s do_not_do_something // do something do_not_do_something: 但如果我们禁用优化,它会变成这样: ldloc.0 ldc.i4.s 10 ceq ldc.i4.0 ceq stloc.1 ldloc.1 brtrue.s do_not_do_something // do something do_not_do_something: 我无法理解这一点。 为什么所有额外的代码,似乎在源中不存在? 在C#中,这相当于: int x, y; // … // y = x […]

有没有办法在C#中挂钩托管函数,就像我在C ++中使用非托管函数一样?

在C ++中,我将得到函数的地址,并将前几个字节覆盖到jmp到我的函数,做一些事情,恢复原始字节,并调用原始函数。 我可以在C#中做这样的事吗?

是否有用于在运行时validation动态程序集的MSIL的API?

使用Reflection.Emit在运行时构建程序集时,我想在保存到光盘之前validation程序集MSIL。 像PEVerify一样,但在运行时。 有这样的API吗?

C#拦截/更改/重定向方法

假设我在第三方dll中有一个私有的,“实例”,非静态的bool方法。 所有这个方法都返回一个值。 没有其他的。 我将如何拦截对此方法的调用,更改它的IL OpCodes /方法体,或将其重定向到额外的,重写或派生的方法。 我不想反编译第三方DLL,手动更改源,并重新编译它。 我也不想将程序集保存到磁盘,因为这也涉及使用“重新编译”的程序集而不是原始程序集。 我基本上希望能够使用原始的dll – 没有替换或文件更改。 我只想做我上面提到的事情。 有没有办法解决这个问题? 如果是这样,你可以详细说明或发布参考/教程/等。 另外,我知道虚拟,覆盖和新的修饰符,但请记住我:没有所说的第三方dll的源,无法访问源,不想用dotPeek和重新编译等东西进行反编译。 谢谢! 编辑:我忘了提及基础架构的其余部分:MainProgram加载ThirdPartyDLL。 MainProgram还加载MyPluginDLL。 我正在尝试从MyPluginDLL更改ThirdPartyDLL中的方法,以便当MainProgram调用所述方法时,它将调用更改的方法。 我希望能够在不保存新assembly并使用新assembly重新启动MainProgram的情况下执行此操作。 基本上,我想在启动时或MainProgram运行时执行此操作。

有没有一种简单的方法来获取C#(或CIL)中当前堆栈帧中的所有局部变量

按照我之前的问题,我想在其中转储堆栈中的所有变量(从当前和所有前一帧),这里可以看到: 有没有办法在运行时检查C#中的堆栈变量? 我被建议手动拦截调用或使用像PostSharp这样的AOP框架来简化这样的任务。 我查看了PostSharp,并且拦截参数不包括当前堆栈帧中的变量。 我想知道是否有一种简单的方法可以自动获取当前堆栈帧中的所有局部变量。 我想我可以执行代码分析并生成将所有这些值复制到集合中的代码,但也许有一个内置机制来完成它。 在此先感谢您的任何建议。 编辑:我应该详细说明为什么我要这样做。 我希望能够在方法中间暂停执行。 如果我有堆栈的内容,我可以稍后恢复执行,甚至序列化它并在另一台机器上继续(假设它是相对简单的代码,因此没有线程或I / O)。 运行代码分析工具是可以的,这将允许我自动生成保存此状态的额外代码。 我想我可能要分析CIL才能做到这一点。

编译器为delegate关键字生成的密封类包含虚拟方法

在C#中使用delegate关键字时,C#编译器会自动生成从System.MulticastDelegate类派生的类。 此编译器生成的类还包含3个方法: Invoke, BeginInvoke and EndInvoke 。 所有这三种方法都标记为public virtual extern但有趣的是,类本身标记为sealed 。 在密封类中定义的虚拟方法不仅违反直觉,而且在C#中实际上是非法的。 所以我的问题是,是否有一个特定的原因,或者它只是其中一个无害的事情,记住一些假设的未来增强? 编辑1: 可能的原因是强制使用’callVirt’IL操作码而不是’调用’,以便在尝试执行这三种方法中的任何一种之前,CLR始终检查委托对象为空? 虽然我不明白为什么delegate在这方面应该是一个特例。 也不是强制使用callvirt的性能打击(虽然它可能是微不足道的) 编辑2: 添加了CIL标记,因为事实certificate定义委托的C#方式实际上是由CIL标准强制执行的。 标准规定(以下不是全文) 代理应具有System.Delegate的基本类型。 代表应宣布密封 ,代表的唯一成员应为此处规定的前两种或全部四种方法。 这些方法应声明为运行时和管理。 它们不应具有身体,因为该身体应由VES自动创建。 委托上可用的其他方法inheritance自基类库中的System.Delegate类。 委托方法是: 实例构造函数 Invoke方法应该是虚拟的 BeginInvoke方法(如果存在)应为虚拟方法 EndInvoke方法应该是虚拟的 所以这绝对不是编译器进程的副作用,或者类似于其他有趣的编译器输出。 如果标准强调某些东西,那必须是出于某种充分的理由和理由。 所以现在的问题是为什么代表们的CIL标准同时强调密封和虚拟? 渔获物在这里吗?: 它们不应具有身体,因为该身体应由VES自动创建。 它们是否标记为虚拟,以便在调用这些方法时可以执行VES / CLR生成的主体?