首页天道酬勤可疑的 Box 操作,操作box

可疑的 Box 操作,操作box

admin 08-30 02:25 373次浏览

今天又在看C#泛型的代码,又有一点小发现...但愿大家没听腻了我说泛型

是这样的,还是我上次写的那两个类:

interface ITest
{
     void testMethod();
}

class Test<T> where T:ITest,new()
{
      public Test()
     {
            t = new T();
      }
      public void foo()
     {
            t.testMethod();
      }
      private T t;
 }

观察Test<T>.foo()函数的IL代码的时候,发现了一个很可疑的box操作:
.method public hidebysig instance void  foo() cil managed
{
  // Code size       17 (0x11)
  .maxstack  8
  IL_0000:  ldarg.0
  IL_0001:  ldfld      !0 class ConsoleApplication1.Test<!0>::t
  IL_0006:  box        !0
  IL_000b:  callvirt   instance void ConsoleApplication1.ITest::testMethod()
  IL_0010:  ret
} // end of method Test::foo

说明一下,那个ConsoleApplication是namespace,!0 是IL中泛型参数T的占位符。
从上面的代码来看,泛型参数的实例 Test<T>::t,被当做一个ValueType,而且在调用相关方法的时候被box成了一个Constraint里定义的接口,然后使用了callvirt来调用接口的虚函数。如此一来,又有box,又有转型的动作,似乎调用方法的开销大了一点

写了一个实现同样功能的多态版本,进行对比:

class TestVirtual
{
      public static void foo(ITest i)
     {
            i.testMethod();
      }
}

相应的foo函数产生的IL代码如下:
.method public hidebysig static void  foo(class ConsoleApplication1.ITest i) cil managed
{
  // Code size       7 (0x7)
  .maxstack  8
  IL_0000:  ldarg.0
  IL_0001:  callvirt   instance void ConsoleApplication1.ITest::testMethod()
  IL_0006:  ret
} // end of method TestVirtual::foo

明显代价要小很多。

并且如果把上述泛型的IL代码改为:
.method public hidebysig instance void  foo() cil managed
{
  // Code size       17 (0x11)
  .maxstack  8
  IL_0000:  ldarg.0
  IL_0001:  ldfld      !0 class ConsoleApplication1.Test<!0>::t
  IL_0006:  box        !0
  IL_000b:  call   instance void !0::testMethod()
  IL_0010:  ret
} // end of method Test::foo

结果会产生一个System.MissingMethodException,提示信息如下:
Unhandled Exception: System.MissingMethodException: Method not found: 'Void System.Object.testMethod()'.
从这里可以看出泛型参数的实例被box成了Object的实例,这到与隐含的泛型参数继承自Object 的Constraints吻合。看样子CLR的泛型支持充其量也就是一些底层的转型动作,而且还加上一个box的开销也不知道和java的泛型比,谁的开销更大一点了。

最后说一些题外话,看到Ninputer在抱怨不能约束ValueType或者ReferenceType,想到上次在C# team的blog里看到过这个事情,确实有准备添加这个功能啊,这里!
  

转载于:https://www.cnblogs.com/想人陪的苗条/archive/2004/03/29/4578.html

IPv6转换价格 基础网络 UNet访问NexusConfig-Ext.JSON.decode():您正在尝试解码无效的JSON字符串:
控件安装成功但没有写入注册表,activex控件未注册怎么办 钉钉机器人定时发送消息,钉钉机器人自动定时通知任务
相关内容