【问题标题】:What is a better way to check that a given object is a particular value type? [closed]检查给定对象是否为特定值类型的更好方法是什么? [关闭]
【发布时间】:2013-07-12 03:30:22
【问题描述】:

以下是拆箱前检查的两种常用方法。

myObject.GetType() == typeof(MyValueType)

IL_0001:  callvirt    System.Object.GetType
IL_0006:  ldtoken     UserQuery.MyValueType
IL_000B:  call        System.Type.GetTypeFromHandle
IL_0010:  call        System.Type.op_Equality


myObject is MyValueType

IL_0001:  isinst      UserQuery.MyValueType

另外,我想知道为什么 C# 调用 System.Type.op_Equality 而不是 ceq 这不是引用相等检查吗?

更新

其实还有第三种方式。 (简而言之,来自 C# 5.0)

MyValueType? x = myObject as MyValueType?;

然后检查x.HasValue并使用x.Value

你会使用这三个中的哪一个?

【问题讨论】:

  • 翻转三面硬币?
  • 我会使用哪一个?当然myObject is MyValueType。这就是is 关键字的用途。我相信编译器会选择它的神器翻译。旁注:对于值类型,两种形式给出相同的结果。但在其他情况下,当然会有所不同。例如myObject is IDisposable 工作正常,而myObject.GetType() 永远不能给出接口类型或抽象类。另一个例子,即使Func<> 是密封类型,myObject is Func<object> 也会为Func<string> 提供真值。协方差。

标签: c# il value-type gettype


【解决方案1】:

我想知道为什么 C# 调用 System.Type.op_Equality 而不是 ceq

因为类型是按值而不是按引用进行比较的。内存中可能有两个类型对象引用相同的类型。

你会使用这三个中的哪一个?

如果您想知道某个实例是否属于特定类型,则有一个运算符专门用于解决该问题并且单独解决该问题is。为什么您会使用专为解决您的问题而设计的工具?如果您要更换屋顶并且可以在屋顶斧头和锤子之间进行选择,我希望您会使用屋顶斧头。

现在,如果您需要同时进行类型测试并获取值,那么我倾向于使用as,因为这是专为解决该问题而设计的运算符。

【讨论】:

  • 我认为is 旨在解决实例是否与给定类型“兼容”,而GetType() 用于解决类型实际上相同的问题。在这种情况下,由于类型是密封的,所以 2 给出相同的结果。但是,我觉得is 有点过度使用了。
  • 使用as我还得带上Nullable,那也太用了吧?它的重量是否比is + 拆箱便宜?
  • 来自 MSDN msdn.microsoft.com/en-us/library/system.type.aspx " 表示类型的 Type 对象是唯一的;也就是说,两个 Type 对象引用当且仅当它们表示相同的类型时才引用相同的对象。这允许比较使用引用相等键入对象”所以它说引用相等
  • @colinfang:你的问题不是更便宜,你的问题是你会使用哪一个?我回答了你问的问题。如果您想知道哪个更便宜的答案:双向编写代码,双向运行,衡量成本,然后您就会知道哪个更便宜。
  • @colinfang:CLR 提供的类型对象保证引用相等。请记住,Type 是未密封的;如果您想创建自己的 Type 对象,则不需要强制引用相等(尽管这样做是个好主意。)因此,C# 编译器不会尝试将类型上的相等操作优化到引用相等; op_Equality 方法将检查引用是否相等。
【解决方案2】:

如果存在重载的== 运算符,则首选它。如果不是,那有什么意义呢?

除了进行测量以找出更快的方法之外,我认为类型相等性检查会更快,因为 JIT 包含一个特殊的优化,可以识别这种模式并最大限度地优化它。另一方面,如果 JIT 识别出您正在转换为值类型(它不可能有子类型),那么 isinst 可能会被编译为相同的指令。

您的第 3 种检查方法无法击败第 2 种,因为您需要 JIT 比以前做更多的事情。充其量这会优化回第二种形式,但鉴于当前 JIT 的优化能力很差,我会感到惊讶。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-07-28
    • 2013-09-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-02-18
    • 2021-02-06
    相关资源
    最近更新 更多