簡體   English   中英

當調用遞歸通用接口上的擴展方法時,結構實例會被裝箱嗎?

[英]Do struct instances get boxed when an extension method on a recursive generic interface is called?

我有一個“遞歸通用接口”:

public interface MyInterface<T> where T : MyInterface<T>
{
    T DoSomething();
}

我在上面定義了一個擴展方法:

public static class MyExtensions
{
    public static T DoSomethingElse<T>(this T t)
        where T : MyInterface<T>
    {
        Console.WriteLine("DoSomethingElse was called.");
        return t.DoSomething();
    }
}

然后,我在struct中實現了該接口:

public struct MyStruct : MyInterface<MyStruct>
{
    public MyStruct DoSomething()
    {
        Console.WriteLine("DoSomething was called.");
        return new MyStruct();
    }
}

然后我在main中調用了擴展方法:

public class Program
{
    static void Main(string[] args)
    {
        MyStruct x = new MyStruct();
        MyStruct y = x.DoSomethingElse();
        Console.ReadKey();
    }
}

問題: 調用DoSomethingElse ,對象MyStruct x裝在MyInterface ,還是擴展方法直接在x上操作?

我有理由相信兩者:

  • x被裝箱:如果接口不是遞歸的,則可能是這種情況,在這里可能就是這種情況,擴展方法需要使用MyInterface類型的MyInterface來進行裝箱
  • x未裝箱:參數T t直接表示結構MyStruct ,因此無需裝箱即可直接傳遞。

我非常努力地想出一種測試方法,但是找不到將結構轉換為接口類型的那一刻的方法。

抱歉,我為這個標題表示歉意,但是我說不出更好的話,如果您可以用更簡單的術語描述問題,請隨時對其進行編輯。

沒有拳擊。

您可以在這里將代碼放入sharplab來看到這一點 沒有box說明。 有一個受限制的虛擬呼叫,在某些情況下可以裝箱,但此處不行。

如果將結構轉換為接口類型,則將顯示以下內容:

MyInterface x = new MyStruct();

但是,調用這樣的泛型方法(無論泛型類型參數是否限於接口類型),都不會裝箱。 當您調用MyExtensions.DoSomethingElse<MyStruct> ,JIT將發射該方法的新實現,該實現專門使用MyStruct因此,不需要裝箱。

MyExtensions.DoSomethingElse執行受限的虛擬調用以調用DoSomething方法。 它主要用於編譯器不確定運行時目標是值類型還是引用類型時,它基本上說“ JIT,您可以弄清楚這一點”。 特別:

  • 如果thisType是值類型,並且thisType實現method則將ptr未經修改地傳遞為call method指令的“ this”指針,以供thisType實現method
  • 如果thisType是值類型,並且thisType不實現method則將ptr取消引用,裝箱並作為“ this”指針傳遞給callvirt method指令。

在這里,我們遇到了第一種情況,因此沒有發生拳擊。 如果您調用了t.GetHashCode()t.GetType() ,那么JIT將向框t發出指令。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM