【问题标题】:C# - <T> object castingC# - <T> 对象转换
【发布时间】:2012-07-12 12:14:19
【问题描述】:

据我所知,如果我们在处理COM 接口,任何简单的转换通常都会触发QueryInterface 例程,该例程用于确定对象是否真正实现了对应的COM 接口。

object whatever;
IComInterface casted = (IComInterface) whatever;

因此,以下代码,取决于编译器和优化可能会触发内部对象转换实现中的QueryInterface

IComInterface comInteface;

// I guess nothing COM-related happens here, but I might be wrong
object whatever = comInteface; 

// This might or might not trigger the 'QueryInterface' call.
IComInterface comInterface2 = (IComInteface) whatever;

问:

假设我有一个通用的List&lt;T&gt; 实例:

List<IComInterface> list = new List<IComInterface>();

现在,我是否有力保证以下代码不会触发基于 QueryInterface 的转换?

List<IComInterface> list = new List<IComInterface>();
IComInterface comInterface = (...); // Somehow got it.
list.Add(comInteface);
IComInterface retrieved = list[0];
  • 在此处使用ArrayList 而不是List&lt;T&gt; 实际上会执行强制转换,因为您必须从无类型的object 实例中获取相应的IComInterface

  • 但是,如果是泛型,我想,一切都应该在没有强制转换的情况下完成,但我实际上并不确定它们在表面下是如何工作的。

  • List&lt;T&gt; 是否仍可能以某种方式与 object 类型一起运行(因此,将在所描述的场景中调用基于 QueryInterface 的强制转换)?

  • 如果上一个问题的答案是“否”,是不是就不能保证任何可能的IList&lt;T&gt; 都一样?

【问题讨论】:

  • 据我所知,当您创建泛型类型时,我认为 .NET 创建了一个新类型的实例 - 因此强类型泛型不会使用 System.Object 引用 - 我可能错了
  • 我不是 100% 确定,所以写评论,一件事是如果你使用 List 不会发生转换,另一件事是你的第二个问题是不相关的,因为 List 实现了 IList .
  • @GuruKara 第二个问题,正如我现在意识到的那样,是愚蠢的,因为有人可以实现IList&lt;T&gt;,它使用object 来存储数据,然后将其转换回:) 所以,我猜,这个问题只是关于List&lt;T&gt;
  • 这可能值得一读:artima.com/intv/generics2.html - 它似乎揭示了 IL 生成的内容以及 CLR 实际在做什么。听起来每个泛型类型都是单独处理的 - 给它一个阅读
  • 有趣的是: Bruce Eckel:你只需要投射。 Anders Hejlsberg:不,实际上你没有。我们可以共享原生镜像,但它们实际上有单独的 VTable。我只是指出,我们在有意义的地方进行了相当积极的代码共享,但我们也非常注意不要在您想要的性能上共享。通常对于值类型,您确实关心 List 是 int。您不希望它们被装箱为对象。装箱值类型是我们可以共享的一种方式,但天哪,这将是一种昂贵的方式。

标签: c# com casting queryinterface


【解决方案1】:

您可以将泛型类型实例(例如List&lt;IComInterface&gt;)视为从泛型类型定义(例如List&lt;T&gt;)创建的类,通过字面替换名称@ 987654323@,名称为 IComInterface。类型不会像在某些语言(最显着的是 Java)中那样被“擦除”,它与泛型类型实例一起保存,因此在泛型类型定义中声明为类型 T 的所有变量都保持强类型化泛型类型实例。

List&lt;IComInterface&gt; 的情况下,只要您在编译时插入已知为IComInterface 类型的对象,就不会与object 进行转换。您帖子中的代码就是这种情况,但可能并非总是如此。例如,当你插入一个动态类型的对象时,编译器会添加一个强制类型转换:

dynamic comInteface = ...
list.Add(comInteface); // There will be an implicit cast here

【讨论】:

    【解决方案2】:

    是的,这是一个相当不错的保证,除非必须,否则编译器不会发出 Opcodes.Castclass IL 指令。类型匹配,因此不需要强制转换。

    这不应该是您普遍关心的问题。 COM 接口的 QI 实现由于 COM 内部的各种原因而受到重创。它总是非常快,比较一个 guid 只需几纳秒。

    【讨论】:

    • 谢谢,这个问题纯粹是学术问题,我并不关心演员的表现(这显然为时过早)。
    • 奇怪,如果它不是性能那么你为什么对学术感兴趣?有点难以正确回答气球问题。
    猜你喜欢
    • 2011-08-05
    • 2017-08-20
    • 2023-04-11
    • 2011-05-06
    • 2012-06-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多