【问题标题】:Direct comparisons of C# Value typesC#值类型的直接比较
【发布时间】:2011-06-03 02:48:15
【问题描述】:

我已阅读以下关于 C# 值类型比较的声明 在 C# 中深入第二版。

第 77 页,

当类型参数不受约束(未对其应用约束)时,您可以使用 == 和 != 运算符,但只能将该类型的值与 null 进行比较。您不能将 T 类型的两个值相互比较。

...

当类型参数被限制为值类型时,== 和 != 根本不能与它一起使用。

如果我理解正确(我不这么认为),它基本上告诉我你不能 使用 == 或 != 比较两种值类型。为什么为什么为什么?

如果能针对这种情况给出一个简单的例子就更好了。谁能给我 对上面这段试图传达的内容有一点了解吗?

【问题讨论】:

  • 我怀疑这是为了避免与运算符重载混淆,因为当泛型类型参数是值类型时,将不会使用重载的 == 运算符。但是,您可以使用 Object.Equals,哪些行为良好的值类型将实现以及与 == 具有相同的行为(对于行为良好的类型)。
  • @Dan Bryant,这不仅是为了避免混淆。无法保证值类型支持 == 和 != 运算符,并且我们不能将 System.Object 实现用于值类型,因为测试引用相等性仅适用于装箱实例。理论上,我们可以指定将操作数装箱以使用引用相等检查,但表达式将始终为假,这显然是无用的。
  • @phoog,静态的Object.Equals 实际上会调用 Object 的 Equals 实现(即使它是装箱的值类型),因此它是比较偶数类型的有效方法。它还处理 null 与值类型的比较。 Object.ReferenceEquals 显式强制检查引用相等,这在引用类型覆盖相等运算符但对空比较情况有错误的情况下会很有帮助(我之前在第三方 API 中遇到过这种情况.)
  • @Dan Bryant,是的,静态(也是实例)对象。Equals 将按照您的描述进行操作。问题是 == 运算符不这样做,因此在泛型类型参数是值类型的情况下,不可能有意义地应用该运算符。

标签: c# generics comparison operators


【解决方案1】:

当限制为一个值类型(第二段)时,它只是意味着这个

static bool TryToCompare<T>(T first, T second) where T : struct
{
    return first == second; // not legal
    return first.Equals(second); // legal
}

没有对泛型的值类型约束,它也这么说(第一段)

static bool TryToCompare<T>(T first, T second) 
{
    return first == second; // not legal
    return first == null; // legal
    return first.Equals(second); // legal
}

如果您将 T 限制为引用类型,则可以使用 == 摆脱困境

static bool TryToCompare<T>(T first, T second) where T : class
{
    return first == second; // legal
    return first == null; // legal
    return first.Equals(second); // legal
}

【讨论】:

  • 第二个函数的第一个示例失败 b/c 我们对 T 没有任何约束,T 可能是结构或类。那是对的吗? -thx
  • 或多或少。不能保证值类型 T 定义了 == 运算符。有关此主题的更多信息,我建议您查看此问题和最佳答案:stackoverflow.com/questions/5808057/…
  • +1:基本上我只对常量使用==!=。如果我没记错的话,您也可以使用default(T) 进行评估。否则,我使用Equals()
【解决方案2】:

对象不可比较,因为使用 == 的比较是测试引用是否相同(内存地址)。你通常会使用 if (string1.Equals(string2))。

我不明白的是,我看到了 == 与字符串一起使用的情况,以及不适用的情况。

【讨论】:

  • 从结果 POV 来看,==string1.Equals(string2) 应该没有什么不同。它们以不同的方式计算,但对于短字符串,Equals 具有轻微的速度优势。好文章在这里:dotnetperls.com/string-equals
  • 在字符串上,当与字符串 as 对象进行比较时,您开始看到“意外”结果。考虑string x = "ONE"; string y = string.Format("ON{0}", "E"); bool b = x == y; bool c = (object)x == (object)y;b 为真,c 为假。但是,将y 更改为string y = "ONE";,现在c 也将为真。
  • 如果对任一字符串操作数的引用具有编译时类型的对象,则 == 将编译为引用相等检查。如果它们都是字符串类型的引用,你会得到操作符的字符串实现。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-09-14
  • 1970-01-01
  • 1970-01-01
  • 2023-03-26
  • 2016-07-21
  • 1970-01-01
  • 2019-09-28
相关资源
最近更新 更多