[英]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
上操作?
我有理由相信兩者:
MyInterface
類型的MyInterface
來進行裝箱 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.