【问题标题】:Is there a reason to do a type comparison this way?有理由以这种方式进行类型比较吗?
【发布时间】:2023-03-10 11:48:02
【问题描述】:

我习惯于看到类似的旧代码

if (true)
{
    ...
}

很明显,有人在进行更改时要么是懒惰,要么是过于谨慎。我今天遇到了这个sn-p,我很好奇这样进行类型比较是否存在功能差异:

private static bool logField(Type t, string fieldname)
{
    if (t.ToString() == typeof (Property).ToString())
    {
        ...
    }
    return true;
}

并这样做:

private static bool logField(Type t, string fieldname)
{
    if (t == typeof (Property))
    {
        ...
    }
    return true;
}

【问题讨论】:

  • 我不知道有什么好的理由这样做。事实上,我认为这是一个错误,因为它至少存在潜在的 NullReferenceException 问题。

标签: c# equals typeof


【解决方案1】:

我会说这通常是懒惰 - 但它可能不是。例如,您可以在同一个有效文件中拥有两种属性类型,但副本不同。如果 typeof(Property) 从一个文件加载它但 t 从另一个文件加载,您的替换会说它们不同,但原始代码会比较说它们是相同的。

这绝对是一种极端情况,您通常首先希望避免这种情况......但这只是可能

【讨论】:

  • 关于两种属性类型的观点非常好。如果要比较类型,请直接进行,而不是通过字符串表示。如果你想比较类型名称(可能是因为你给出的原因),那么就这样做。虽然如果代码依赖于比较类型名称,我认为注释是有序的。
  • 我不知道所涉及的 DLL 会从同一个 AppDomain 中的多个位置加载的任何情况(我在不同的应用程序中遇到了这个问题)。当您说“相同的有效文件,但不同的副本”时,这就是您所指的吗?
  • @arootbeer:这种情况通常发生的方式是有人通过其程序集名称加载程序集,并且,奇怪的是,第二次通过其路径加载它我>。 CLR 的原因是,如果您在已按名称加载时通过其路径重新加载已加载的程序集,那么您必须打算将这些程序集 及其中的类型视为 不同。然后,您可以很容易地陷入非常混乱的境地,即拥有两个不被视为相同的相同类型。苏珊娜·库克在早期写了很多关于这方面的博客文章,请参阅她的博客了解详细信息。
  • @Eric Lippert - 我最近在构建插件系统的情况下遇到了这个问题,我在两个地方有一个 DLL (NServiceBus.dll) 的副本:bin 文件夹(它是由容器正确引用)和插件文件夹(它由消息 dll 引用,我错误地将其复制到那里)。当加载器加载插件目录中的 DLL 时,它会拾取第二个 NSB 实例,因为它位于引用插件程序集所在的本地。然后,当需要检查插件中的消息是否为 NSB.IMessage 时,它​​决定它们不是
  • 续。 - 因为它们是由 DLL 的两个独立实例定义的类型。我认为这可能不像从同一个地方显式加载同一个 DLL 那样奇怪,这就是我提出它的原因。
【解决方案2】:

我想不出任何好的理由。

事实上,如果t为null,前者会抛出。

【讨论】:

  • 它确实考虑了命名空间 - Type.ToString 包括命名空间。
  • @Jon 你是对的。我被 Reflector 误导了(Type.ToString 不包括命名空间,但 RuntimeType 覆盖了它)
【解决方案3】:

第一个比较字符串的引用,而第二个实际检查 t 是否属于 Property 类型。

第一个总是“正确的”,因为两个字符串引用同一个对象,但第二个是检查 t 是否属于 Property 类型的正确方法。

进行类型检查的等效且更易读的方法是

if (t is Property)

【讨论】:

    【解决方案4】:

    不,获取相同类型的 2 个实例的类型对象将始终返回对内存中相同类型对象的引用。这意味着执行引用相等检查 (==) 就足够了。

    基本上,调用: if (t.ToString() == typeof (Property).ToString())

    将对同一个对象调用两次 ToString(),其中 t 是“属性”类型。

    【讨论】:

    • 很高兴知道运行时会为 typeof() 的每个实例返回相同的引用,但正如 Jon Skeet 所提到的,如果您从 DLL 的两个不同副本加载相同的类型,运行时认为它们是不同的类型。
    【解决方案5】:

    我想说第一种方法可能是由不熟悉 C# 的人完成的,不必偷懒。字符串比较在大多数情况下都有效,除了:

    1. 如果t 为空,则会抛出空引用异常。
    2. 它不考虑命名空间。

    我会推荐第二种情况,除非您需要 #2 边缘情况。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-07-23
      • 2020-11-03
      • 1970-01-01
      • 2019-09-28
      • 2012-12-20
      • 1970-01-01
      • 2019-01-25
      相关资源
      最近更新 更多