首頁>Program>source

给出以下代碼:

public class C
{
    public void M()
    {
        var x = 5;
        Action<int> action = y => Console.WriteLine(y);
    }
}

使用VS2013,.NET 4.5.查看反編譯的代碼時,我们可以看到編譯器正在將呼叫快取在呼叫站點:

public class C
{
    [CompilerGenerated]
    private static Action<int> CS$<>9__CachedAnonymousMethodDelegate1;
    public void M()
    {
        if (C.CS$<>9__CachedAnonymousMethodDelegate1 == null)
        {
            C.CS$<>9__CachedAnonymousMethodDelegate1 = new Action<int>(C.<M>b__0);
        }
        Action<int> arg_1D_0 = C.CS$<>9__CachedAnonymousMethodDelegate1;
    }
    [CompilerGenerated]
    private static void <M>b__0(int y)
    {
        Console.WriteLine(y);
    }
}

尋找在罗斯林反編譯相同的代碼(使用TryRoslyn),产生以下輸出:

public class C
{
    [CompilerGenerated]
    private sealed class <>c__DisplayClass0
    {
        public static readonly C.<>c__DisplayClass0 CS$<>9__inst;
        public static Action<int> CS$<>9__CachedAnonymousMethodDelegate2;
        static <>c__DisplayClass0()
        {
            // Note: this type is marked as 'beforefieldinit'.
            C.<>c__DisplayClass0.CS$<>9__inst = new C.<>c__DisplayClass0();
        }
        internal void <M>b__1(int y)
        {
            Console.WriteLine(y);
        }
    }
    public void M()
    {
        Action<int> arg_22_0;
        if (arg_22_0 = C.<>c__DisplayClass0.CS$<>9__CachedAnonymousMethodDelegate2 == null)
        {
            C.<>c__DisplayClass0.CS$<>9__CachedAnonymousMethodDelegate2 =
                            new Action<int>(C.<>c__DisplayClass0.CS$<>9__inst.<M>b__1);
        }
    }
}

我们現在可以看到,该代表現在被提升為 C內部的私有類 ,当我们關闭例項變數/欄位(關闭)時,我们经常会看到類似的行為。

我知道這是一个實現细节,隨時可能更改.

我仍然想知道,將委託提升到一个新類並在簡單地將其快取在呼叫站點的地方快取在那裏有什麼好處?

Edit:

此問题讨論的行為与此處要求的相同。

最新回復
  • 5月前
    1 #

    是.最重要的是,包含lambda實現的方法現在是例項方法。

    您可以看到作為中間人的委託通過Invoke接收例項呼叫並根据實現方法的呼叫約定排程该呼叫.

    請註意,存在平臺ABI要求,這些要求指定如何傳遞引數,如何返迴結果,通過寄存器傳遞哪些引數以及在哪些引數中傳遞" this"等.违反這些規則可能会對依赖堆棧遍歷的工具(例如除錯器)产生嚴重影响。

    現在,如果實現方法是例項方法,則在委託內部唯一需要發生的就是將" this"(即在呼叫時的委託例項)修補為封闭的Target物件.此時,由於其他所有內容都已经存在,因此委託可以直接跳轉到實現方法主體.在许多情况下,這比在實現方法是靜態方法的情况下所要做的工作要少得多。

  • 5月前
    2 #

    Still I wonder, what are the benefits of lifting the delegate into a new class and caching it there over simply caching it at the call site?

    您真的錯過了另一个真的重要细节-它現在是一个例項方法.我相信這是關键.在IIRC中,發現呼叫由例項方法"支援"的委託要比呼叫由靜態方法支援的委託要快,這是更改的動機。

    這是所有傳闻,在CodeMash与Dustin Campbell和Kevin Pilch-Bisson(都来自罗斯林团队)共度時光,使人迴想起了,但鉴於您所顯示的代碼,這才有意義。

    (我還没有為我自己驗證效能差異,它听起来很像,就像倒退一樣……但是CLR內部結構可能很有趣……)

  • 如何使用Excel VBA對base64有效地編碼字元串?
  • javascript:為什麼不赞成使用windowshowModalDialog? 用什麼代替呢?