当前位置:  开发笔记 > 编程语言 > 正文

当作为具有接口约束的通用参数传递时,值类型是否装箱?

如何解决《当作为具有接口约束的通用参数传递时,值类型是否装箱?》经验,为你挑选了1个好方法。

(作为回答这个问题的研究结果,我(我想我已经!)确定答案是"不".但是,我不得不在几个不同的地方看看这个,所以我觉得还有这个问题很有价值.但如果社区投票结束,我不会感到沮丧.)

例如:

void f(T val) where T : IComparable
{
   val.CompareTo(null);
}

void g()
{
   f(4);
}

4盒装?我知道明确地将值类型转换为它实现触发装箱的接口:

((IComparable)4).CompareTo(null); // The Int32 "4" is boxed

我不知道的是,将值类型作为具有接口约束的泛型参数传递是否等于执行转换 - 语言"其中T是IC Comparable" 类似于建议转换,但只是转变TIComparable似乎它会打败通用的全部目的!

为了澄清,我想确保在上面的代码中没有发生这些事情:

    g调用时f(4),由于对参数类型有约束,因此4被强制转换IComparable为.IComparablef

    假定(1)不发生,内f,val.CompareTo(null)不投valInt32IComparable为了调用CompareTo.

但我想了解一般情况; 不只是ints和IComparables 会发生什么.

现在,如果我将以下代码放入LinqPad:

void Main()
{
    ((IComparable)4).CompareTo(null);
    f(4);
}

void f(T val) where T : IComparable
{
   val.CompareTo(null);
}

然后检查生成的IL:

IL_0001:  ldc.i4.4    
IL_0002:  box         System.Int32
IL_0007:  ldnull      
IL_0008:  callvirt    System.IComparable.CompareTo
IL_000D:  pop         
IL_000E:  ldarg.0     
IL_000F:  ldc.i4.4    
IL_0010:  call        UserQuery.f

f:
IL_0000:  nop         
IL_0001:  ldarga.s    01 
IL_0003:  ldnull      
IL_0004:  constrained. 01 00 00 1B 
IL_000A:  callvirt    System.IComparable.CompareTo
IL_000F:  pop         
IL_0010:  ret  

很明显,拳击是按照预期的显式转换发生的,但是拳击f本身*或其中的呼叫站点都不明显Main.这是个好消息.但是,这也只是一种类型的一个例子.所有情况都可以假设这种缺乏拳击的东西吗?


*这篇MSDN文章讨论了constrained前缀和状态,callvirt只要被调用的方法在类型本身上实现(而不是基类),使用它的前缀和状态就不会触发值类型的装箱.我不确定的是当我们到达这里时类型是否仍然值类型.



1> Sriram Sakth..:

正如你已经想到的那样,当a struct传递给泛型方法时,它不会被装箱.

Runtime为每个"Type Argument"创建新方法.当您使用值类型调用泛型方法时,实际上是在调用为​​各个值类型创建的专用方法.所以不需要拳击.

当调用未在结构类型中直接实现的接口方法时,将发生装箱.Spec在这里调用它:

如果thisType是一个值类型而thisType没有实现方法,则ptr被解除引用,装箱,并作为'this'指针传递给callvirt方法指令.

最后一种情况只有在Object,ValueType或Enum上定义方法并且不被thisType覆盖时才会发生.在这种情况下,装箱会导致原始对象的副本.但是,由于Object,ValueType和Enum的方法都没有修改对象的状态,因此无法检测到此事实.

因此,只要您明确[1]在结构本身中实现接口成员,就不会发生装箱.

通用方法如何,何时何地具体化?

1.不要与Explicit接口实现混淆.这就是说你的接口方法应该在struct本身而不是它的基本类型中实现.

推荐阅读
LEEstarmmmmm
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有