C#调用
Math.Pow(2,3);
Run Code Online (Sandbox Code Playgroud)
在ILDASM中:
ldc.r8 2.
ldc.r8 3.
call float64[mscorlib]System.Math::Pow(float64, float64)
Run Code Online (Sandbox Code Playgroud)
有人可以告诉我如何通过ILGenerator发出该调用语句吗?谢谢.
我试图运行出现的文档页面上的示例代码System.Reflection.Emit.LocalBuilder类,但它看来,调用LocalBuilder.SetLocalSymInfo(string, int, int)没有做任何事情,因为IL反汇编显示了这个作为IL的SampleAssembly.dll:
.method public static string Function1(int32 A_0) cil managed
{
// Code size 10 (0xa)
.maxstack 1
.locals init (string V_0,
int32 V_1)
IL_0000: ldarg.0
IL_0001: stloc.1
IL_0002: ldstr "string value"
IL_0007: stloc.0
IL_0008: ldloc.0
IL_0009: ret
} // end of method Example::Function1
Run Code Online (Sandbox Code Playgroud)
为什么不在Dissasembler中列出变量名(myString和myInt)?
环境信息:
编辑:正如我在评论中提到的,有一个SampleAssembly.pdb文件与SampleAssembly.dll文件一起生成.
众所周知,字符串是隐式实例化的,这意味着我们不必使用new它来获取对象的对象的引用.
因此,我一直认为框架正在处理这个问题,因此如果我这样做,我会得到相同的IL:
String first = new String(new char[] {'a'});
string second = "a";
Run Code Online (Sandbox Code Playgroud)
然而,似乎第一行是使用newobj instance void [mscorlib]System.String::.ctor(char[])
和第二行完成的ldstr "a".
那么为了获得一个字符串引用,ldstr内部调用newobj,我在哪里可以看到规范/细节来支持它?
我一直在使用LINQPad中的一些C#语句来理解发出的中间语言代码.
我首先尝试了以下代码:
var Container = new {Name = "James"};
Console.WriteLine(Container.Name);
Run Code Online (Sandbox Code Playgroud)
并且看到以下六行IL发射:
IL_0001: ldstr "James"
IL_0006: newobj <>f__AnonymousType0<System.String>..ctor
IL_000B: stloc.0
IL_000C: ldloc.0
IL_000D: callvirt <>f__AnonymousType0<System.String>.get_Name
IL_0012: call System.Console.WriteLine
Run Code Online (Sandbox Code Playgroud)
这是我所期望的,并且非常好地演示了匿名类型是如何只读/不可变的,因为没有set_Name属性.
接下来我尝试了这些陈述:
dynamic Container = new System.Dynamic.ExpandoObject();
Container.Name = "James";
Console.WriteLine(Container.Name);
Run Code Online (Sandbox Code Playgroud)
这会导致大量的IL被释放.我不会在这里粘贴它,但你可以在这个pastebin中找到它.
我理解在管理动态类型和ExpandoObject方面存在相当多的开销,但我不明白为什么看起来System.Console.WriteLine在这种情况下调用是通过内部反射来执行的.
IL_0072: ldstr "WriteLine"
....
IL_00BF: ldtoken System.Console
Run Code Online (Sandbox Code Playgroud)
在第一段代码中,在检索并存储属性之后,它是一个调用的单行IL语句System.Console.WriteLine.
那么为什么一个dynamic类型的呼叫需要额外的所有这些?
我刚开始看一下IL,我很好奇我的尝试(如下所示)从编译器输出中删除多余的代码有任何意想不到的副作用.
关于结果的几个问题:
原始C#代码:
class Program {
public static int Main() {
return Add(1, 2);
}
public static int Add(int a, int b) {
return a + b;
}
}
Run Code Online (Sandbox Code Playgroud)
csc.exe用ildasm.exe(原始)编译和拆解它:
.method public hidebysig static int32 Main() cil managed
{
.entrypoint
.maxstack 2
.locals init (int32 V_0)
IL_0000: nop
IL_0001: ldc.i4.1
IL_0002: ldc.i4.2
IL_0003: call int32 Program::Add(int32, int32)
IL_0008: stloc.0
IL_0009: br.s IL_000b
IL_000b: ldloc.0
IL_000c: ret
}
.method public hidebysig static int32 Add(int32 a, …Run Code Online (Sandbox Code Playgroud) 我有一些我写的自定义IL,它不会通过PEVerify.我得到的错误是
$ peverify foo.exe Microsoft (R) .NET Framework PE Verifier. Version 4.0.30319.17929 Copyright (c) Microsoft Corporation. All rights reserved. [IL]: Error: [Z:\virtualbox_shared\foo.exe : HelloWorld.Program::Main][offset 0x00000021] Stack height at all points must be determinable in a single forward scan of IL. 1 Error(s) Verifying foo.exe
然而,该程序将运行正常,没有任何例外.以下是相关方法的IL:
.method private static hidebysig
default void Main (string[] args) cil managed
{
// Method begins at RVA 0x2050
.entrypoint
// Code size 54 (0x36)
.maxstack 2
//custom IL
ldc.i4 1
ldc.i4 1
ceq
switch(first, second) …Run Code Online (Sandbox Code Playgroud) 我需要找出一个通用结构的大小(我不能像sizeof(T)或使用Marshal.SizeOf(...)0>给我一个错误)
所以我写道:
public static class HelperMethods
{
static HelperMethods()
{
SizeOfType = createSizeOfFunc();
}
public static int SizeOf<T>()
{
return SizeOfType(typeof(T));
}
public static readonly Func<Type, int> SizeOfType = null;
private static Func<Type, int> createSizeOfFunc()
{
var dm = new DynamicMethod("SizeOfType", typeof(int), new Type[] { typeof(Type) });
ILGenerator il = dm.GetILGenerator();
il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Sizeof); //needs to be il.Emit(OpCodes.Sizeof, typeof(something))
il.Emit(OpCodes.Ret);
var func = (Func<Type, int>)dm.CreateDelegate(typeof(Func<Type, int>));
return func;
}
}
Run Code Online (Sandbox Code Playgroud)
一个不同之处是il.Emit(OpCodes.Sizeof)需要一个参数,在创建方法(SizeOfType)时我无法传递它.如何使用IL将堆栈中的参数传递给il.Emit(OpCodes.Sizeof)?(或者是一个不同的解决方案,但我想缓存一个函数(委托)而不是第二个答案中提出的结果)
我正在使用Unity3D for Mobile的免费版本,它不允许我System.Net.Sockets在移动设备上使用命名空间.问题是我正在使用.dll引用的编译库(即IKVM)System.Net.Sockets.我实际上并没有在IKVM中使用引用该引用的类System.Net.Sockets,因此我没有购买$ 3000 Unity Pro移动许可证,而是创建了一个Sockets名为的命名空间的存根库,dudeprgm.Net.Sockets它只是用存根替换了所有的类和方法(我这样做了Mono源代码).
我需要将System.Net.Sockets.*我的dll中的所有引用替换为dudeprgm.Net.Sockets.*.我知道这样的事情是可能的并且由其他人完成(参见下面的编辑,在页面底部).我想知道自己该怎么做.
我能够使用Mono.Cecil提出以下代码.
它遍历所有IL指令,检查操作数是否为a InlineType,然后检查内联类型是否属于其中System.Net.Sockets,然后将其重命名为dudeprgm.Net.Sockets并写入.**我不确定这是否是在Mono.Cecil中进行"查找和替换"的正确方法.问题是,这并没有抓住所有Sockets用法(见下文).
private static AssemblyDefinition stubsAssembly;
static void Main(string[] args) {
AssemblyDefinition asm = AssemblyDefinition.ReadAssembly(args[0]);
stubsAssembly = AssemblyDefinition.ReadAssembly("Socket Stubs.dll");
// ...
// Call ProcessSockets on everything
// ...
asm.Write(args[1]);
}
/*
* This will be run on every property, constructor and method …Run Code Online (Sandbox Code Playgroud) double在没有抛出异常的情况下,在IL中检测值是否为有限值(NaN和正/负无穷大)的最快方法是什么?
我正在考虑以下方法(仅为了方便读者使用c#表示法,在我的项目中,我使用的是IL):
!double.IsNaN(x) && !double.IsInfinity(x) - 最明显的,也可能是最慢的,因为涉及2个方法调用.
(*(((long*) &x)) & 0x7fffffffffffffffL) < 0x7ff0000000000000L
或在IL:
ldloca x
conv.u
ldind.i8
ldc.i8 0x7fffffffffffffff
and
ldc.i8 0x7ff0000000000000
clt
Run Code Online (Sandbox Code Playgroud)
我对第二种方法的问题是:
根据我的研究,这应该精确地确定任何给定是否x是有限的.这是真的?
它是解决IL中任务的最佳方式(性能方面),还是有更好(更快)的解决方案?
PS我非常感谢建议运行我自己的基准并找出答案,并且肯定会这样做.只是想到也许有人已经有类似的问题,并知道答案.PPS是的,我意识到我们在这里谈论的是纳秒,是的,它们对我的具体情况很重要
这段代码
Regex regex = new Regex("blah", RegexOptions.Singleline & RegexOptions.IgnoreCase);
Run Code Online (Sandbox Code Playgroud)
编译后在ILSpy中看起来像这样:
Regex regex = new Regex("blah", RegexOptions.None);
Run Code Online (Sandbox Code Playgroud)
为什么会发生这种情况,并且它是正则表达式在.Net 3.5中不匹配的原因吗?在4.5它工作.