代码之家  ›  专栏  ›  技术社区  ›  H. Saleh

当调用递归泛型接口上的扩展方法时,结构实例是否被装箱?

  •  2
  • H. Saleh  · 技术社区  · 5 年前

    我有一个“递归通用接口”:

    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();
        }
    }
    

    然后我在一个结构中实现了接口:

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

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

    DoSomethingElse MyStruct x 陷入困境 MyInterface ,或者扩展方法直接对 x ?

    我有理由相信:

    • 我的接口 为拳击做手术
    • x未装箱:参数 T t 表示结构 MyStruct

    很抱歉,我的标题很糟糕,但我无法更好地表达它,请随时编辑它,如果你可以描述更简单的条款的问题。

    1 回复  |  直到 5 年前
        1
  •  3
  •   canton7    5 年前

    没有拳击。

    你可以把你的代码放进sharplab here . 不 box 可以 在某些情况下是盒子,但在这里不是。

    如果将结构强制转换为其接口类型,则将显示以下框:

    MyInterface x = new MyStruct();
    

    但是,像这样调用泛型方法(无论泛型类型参数是否被约束到接口类型)并不会阻塞。当你打电话的时候 MyExtensions.DoSomethingElse<MyStruct> ,方法的新实现由JIT发出,它专门使用 MyStruct

    MyExtensions.DoSomethingElse 做一个 constrained virtual call 调用 DoSomething 方法。这主要是在编译器不确定目标在运行时是值还是引用类型时使用的,它基本上是说“JIT,你来解决这个问题”。明确地:

    • thisType 是值类型,并且 这种类型 method 然后 ptr 作为指向 call 方法 方法 通过 .
    • 是值类型,并且 这种类型 不执行 然后 callvirt 方法 说明。

    t.GetHashCode() t.GetType() ,则JIT将向box发出指令 t