标签: il

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

delegate关键字在C#所使用的,C#编译器自动生成从派生的类System.MulticastDelegate的类.

这个编译器生成的类也包含3个方法:Invoke, BeginInvoke and EndInvoke.

所有这三种方法都有标记,public virtual extern但有趣的是,类本身已被标记sealed.

在密封类中定义的虚拟方法不仅违反直觉,而且在C#中实际上是非法的.

所以我的问题是,是否有一个特定的原因,或者它只是其中一个无害的事情,记住一些假设的未来增强?

编辑1:

可能的原因是强制使用'callVirt'IL操作码而不是'call',以便在尝试执行这三种方法中的任何一种之前,CLR始终检查委托对象为空?虽然我不明白为什么delegate在这方面应该是一个特例.

也不是强制使用的性能打击callvirt(虽然它可能是微不足道的)

编辑2:

添加了CIL标记,因为事实证明定义委托的C#方式实际上是由CIL标准强制执行的.标准规定(以下不是全文)

代理应具有System.Delegate的基本类型.代表应宣布密封,代表的唯一成员应为此处规定的前两种或全部四种方法.这些方法应声明为运行时和管理.它们不应具有身体,因为该身体应由VES自动创建.委托上可用的其他方法继承自基类库中的System.Delegate类.委托方法是:

  1. 实例构造函数
  2. Invoke方法应该是虚拟的
  3. BeginInvoke方法(如果存在)应为虚拟方法
  4. EndInvoke方法应该是虚拟的

所以这绝对不是编译器进程的副作用,或者类似于其他有趣的编译器输出.

如果标准强调某些东西,那必须是出于某种充分的理由和理由.

所以现在的问题是为什么代表们的CIL标准同时强调密封和虚拟?

渔获物在这里吗?:

它们不应具有身体,因为该身体应由VES自动创建.

它们是否标记为虚拟,以便在调用这些方法时可以执行VES/CLR生成的主体?

.net c# il delegates cil

18
推荐指数
2
解决办法
1980
查看次数

在C#中执行.NET IL代码

有没有办法在C#中执行一系列IL代码,比如C/C++中的shell代码?

我想创建一个方法,将其转换为IL代码,对其进行模糊处理并存储在一个字节数组中,最后要执行它来解密数组内容并执行IL代码.

例如,这是我的C#代码:

 static int MyMethod(string A, int B)
 {
    B += 10;
    if (A.Equals("A"))
        B = 0;
    return B;
 }
Run Code Online (Sandbox Code Playgroud)

现在我将它转换为IL代码:

 private static int MyMethod(string A, int B)
  {
    locals: int local_0,
            bool local_1

    /* 0000025C 00             */ nop
    /* 0000025D 03             */ ldarg_1 // int B
    /* 0000025E 1F 0A          */ ldc_i4_s 10
    /* 00000260 58             */ add
    /* 00000261 10 01          */ starg_s arg_1 // int B
    /* 00000263 02             */ ldarg_0 // string A
    /* 00000264 …
Run Code Online (Sandbox Code Playgroud)

.net c# il

18
推荐指数
1
解决办法
2788
查看次数

为什么在这种情况下使用'br.s'IL操作码?

出于教育目的,我正在学习一些IL(主要是因为我很好奇发生了什么'%'在幕后(原来是rem)并开始离题......).

我写了一个方法,只是返回true来解决一些问题并且想知道'br.s'操作码:

.method public hidebysig static bool  ReturnTrue() cil managed
{
  // Code size       7 (0x7)
  .maxstack  1
  .locals init ([0] bool CS$1$0000)
  IL_0000:  nop
  IL_0001:  ldc.i4.1
  IL_0002:  stloc.0
  IL_0003:  br.s       IL_0005
  IL_0005:  ldloc.0
  IL_0006:  ret
} // End of method Primes::ReturnTrue
Run Code Online (Sandbox Code Playgroud)

在ldc.i4.1在堆栈上推送1并且stloc.0将其放在第0个本地之后,br.s基本上(据我所知)在行IL_0005处对ldloc.0执行'goto'.

为什么是这样?为什么没有IL_0004线,所以这可以省略?

c# il

18
推荐指数
2
解决办法
3365
查看次数

我能正确理解这个MSIL代码吗?

我在C#中有以下代码

// test.Program
private static void Main()
{
    int x = 5;
    int y = 100;
    Console.WriteLine(y + ", " + x);
}
Run Code Online (Sandbox Code Playgroud)

而且我正在阅读IL代码,我之前从未编写过程序集,所以我问我每行的功能是否正确.

.method private hidebysig static 
    void Main () cil managed 
{
    // Method begins at RVA 0x2058
    // Code size 33 (0x21)
    .maxstack 3 // maximum stack in this method is 3
    .entrypoint // method is initial entry point
    .locals init ( // reserves memory for x and y variables
        [0] int32 x, // x variable is …
Run Code Online (Sandbox Code Playgroud)

.net c# il cil ilasm

17
推荐指数
1
解决办法
1368
查看次数

将C#代码转换为IL代码

我如何获得C#代码的IL代码?我可以使用extern库或内部函数吗?

编辑:我想用我的应用程序在MessageBox中显示IL代码.

.net c# il

16
推荐指数
3
解决办法
1万
查看次数

为什么在将C#代码编译成IL时会创建.ctor()?

有了这个简单的C#代码,我就跑了csc hello.cs; ildasm /out=hello.txt hello.exe.

class Hello
{
    public static void Main()
    {
        System.Console.WriteLine("hi");
    }
}
Run Code Online (Sandbox Code Playgroud)

这是来自ildasm的IL代码.

.class private auto ansi beforefieldinit Hello
       extends [mscorlib]System.Object
{
  .method public hidebysig static void  Main() cil managed
  {
    .entrypoint
    // Code size       13 (0xd)
    .maxstack  8
    IL_0000:  nop
    IL_0001:  ldstr      "hi"
    IL_0006:  call       void [mscorlib]System.Console::WriteLine(string)
    IL_000b:  nop
    IL_000c:  ret
  } // end of method Hello::Main

  .method public hidebysig specialname rtspecialname 
          instance void  .ctor() cil managed
  {
    // Code size       7 (0x7) …
Run Code Online (Sandbox Code Playgroud)

c# il csc ildasm

16
推荐指数
2
解决办法
1万
查看次数

为什么c#编译器在某些情况下会发出newobj/stobj而不是'call instance .ctor'来进行struct初始化

这里有一些c#的测试程序:

using System;


struct Foo {
    int x;
    public Foo(int x) {
        this.x = x;
    }
    public override string ToString() {
        return x.ToString();
    }
}

class Program {
    static void PrintFoo(ref Foo foo) {
        Console.WriteLine(foo);
    }

    static void Main(string[] args) {
        Foo foo1 = new Foo(10);
        Foo foo2 = new Foo(20);

        Console.WriteLine(foo1);
        PrintFoo(ref foo2);
    }
}
Run Code Online (Sandbox Code Playgroud)

这里反汇编编译方法主要:

.method private hidebysig static void Main (string[] args) cil managed {
    // Method begins at RVA 0x2078
    // Code size 42 (0x2a)
    .maxstack …
Run Code Online (Sandbox Code Playgroud)

.net c# il

16
推荐指数
1
解决办法
1389
查看次数

.NET开发人员*真的应该花时间学习C以获得低级别的曝光吗?

当Joel Spolsky和Jeff Atwood在他们的播客中就程序员是否应该学习C而开始存在分歧时,无论他们的行业和交付平台如何,它在开发者社区中引发了一场爆炸性的辩论,这可能仍然在今天的某些群体中肆虐.我一直在阅读一些程序员博主的一些段落,他们对此事采取了行动.来自双方的争论当然具有重要性,我所没有发现的是一个与开发人员专注于.NET Framework的观点截然不同的视角.几乎所有人都在评论一般的程序员观点.

我想要的是什么?回想一下杰夫阿特伍德的观点,即大多数时候开发者处于如此高水平的花费将是学习业务/领域,除了学习技术以实现这些领域要求所需的一切.在我的工作经历中,这是对许多人工作生活的非常准确的描述.现在假设.NET开发人员可以派生的"课外"学习的时候,应该为C?

为了记录,我自己在学校里学习过C,我完全理解和欣赏支持者的推理.但是,在考虑事情时,我个人认为.NET开发人员不应该直接进入C.因为,我希望更多的开发人员需要花些时间学习的东西是 - MSILCLR.

也许我被一群不同寻常的同事困住了,我不知道,但在我看来很多人并没有意识到他们的C#或VB代码在JIT进入之前首先在IL编译并使其成为原始机器码.大多数人不知道的IL,并且在如何不感兴趣准确的CLR处理他们编写的代码.通过C#阅读Jeffrey Richter的CLR对我来说在很多方面都让我感到震惊; 很高兴我读到它,尽管同事们认为它"太低了".我不是IL的专家,但是在基础知识方面,我发现自己更容易跟随他的文本,因为我已经熟悉了IL的堆栈行为.我发现自己拆解程序集以查看在编写某些代码时IL的结果.

我学习了CLR和MSIL,因为我知道这是我下面的直接层.允许我执行自己的工作层的图层.C,实际上是进一步下降.更接近我们的"现实"的是CLR和MSIL.这就是为什么我会建议其他人去那些,因为我没有看到足够的人在钻研那层.或者,您的团队是否已全部熟悉MSIL?

c clr il

15
推荐指数
3
解决办法
1418
查看次数

我可以强制编译器优化特定方法吗?

是否有一个属性可以告诉编译器必须始终优化方法,即使/o+未设置全局编译器开关?

我问的原因是因为我想要动态创建一个基于现有方法的IL代码的方法; 当代码被优化时,我想要做的操作相当容易,但由于编译器生成了额外的指令,因此在非优化代码中变得非常困难.


编辑:关于非优化的更多细节困扰我...

让我们考虑以下阶乘函数的实现:

static long FactorialRec(int n, long acc)
{
    if (n == 0)
        return acc;
    return FactorialRec(n - 1, acc * n);
}
Run Code Online (Sandbox Code Playgroud)

(注意:我知道有更好的方法来计算阶乘,这只是一个例子)

在启用优化的情况下生成的IL非常简单:

IL_0000:  ldarg.0     
IL_0001:  brtrue.s    IL_0005
IL_0003:  ldarg.1     
IL_0004:  ret         
IL_0005:  ldarg.0     
IL_0006:  ldc.i4.1    
IL_0007:  sub         
IL_0008:  ldarg.1     
IL_0009:  ldarg.0     
IL_000A:  conv.i8     
IL_000B:  mul         
IL_000C:  call        UserQuery.FactorialRec
IL_0011:  ret         
Run Code Online (Sandbox Code Playgroud)

但是未经优化的版本是完全不同的

IL_0000:  nop         
IL_0001:  ldarg.0     
IL_0002:  ldc.i4.0    
IL_0003:  ceq         
IL_0005:  ldc.i4.0    
IL_0006:  ceq         
IL_0008:  stloc.1     
IL_0009:  ldloc.1     
IL_000A:  brtrue.s    IL_0010
IL_000C:  ldarg.1 …
Run Code Online (Sandbox Code Playgroud)

c# compiler-construction optimization il

15
推荐指数
1
解决办法
1144
查看次数

深入了解IL对.net开发的重要性

当我主要使用c ++时,虽然了解汇编并写了一些非试验性的asm代码是至关重要的,这样我才能真正理解正在发生的事情.我现在主要做.net,虽然我对IL有所了解,但我并不精通.

IL是一个应该具备知识的技能,还是将更全面地学习IL继续告知我如何使用和编写.net代码?

.net il

14
推荐指数
3
解决办法
772
查看次数

标签 统计

il ×10

c# ×8

.net ×6

cil ×2

c ×1

clr ×1

compiler-construction ×1

csc ×1

delegates ×1

ilasm ×1

ildasm ×1

optimization ×1