6

根据它说的类型参数约束(C#编程指南)文档,我引用:

应用 where T : class 约束时,请避免在类型参数上使用 == 和 != 运算符,因为这些运算符将仅测试引用标识,而不是值相等。即使这些运算符在用作参数的类型中被重载也是如此。下面的代码说明了这一点;即使 String 类重载了 == 运算符,输出也是错误的。

使用以下示例:

public static void OpTest<T>(T s, T t) where T : class
{
    System.Console.WriteLine(s == t);
}
static void Main()
{
    string s1 = "target";
    System.Text.StringBuilder sb = new System.Text.StringBuilder("target");
    string s2 = sb.ToString();
    OpTest<string>(s1, s2);
}

但是,ReSharper(我刚刚开始使用演示/试用版来查看它是否对我有价值)提供了一个提示/提示,可以对参数进行空值检查,如下所示:

public Node(T type, Index2D index2D, int f, Node<T> parent)
{
    if (type == null) throw new ArgumentNullException("type");
    if (index2D == null) throw new ArgumentNullException("index2D");
    if (parent == null) throw new ArgumentNullException("parent");
}

(T 受 约束where T : class, new()

我能否安全地遵循 ReSharper 而不会遇到 C# 文档试图告诉我避免的问题?

4

5 回答 5

7

是的,这很好。文档说不要比较两个参数,因为您正在进行参考比较。ReSharper 建议的代码只是确保您传递的引用不为空,因此这样做是安全的。

在我看来,C# 文档建议您不要这样做的主要原因是,例如,如果您==使用作为传递的两个字符串进行操作T1T2它将进行参考比较。任何其他时间您都stringA == stringB将与字符串类中的重载进行值比较。它实际上只是警告不要进行这些类型的比较,因为通常使用的运算符重载(如果您在本地范围内声明的两种类型上使用该运算符)不是。

于 2013-09-25T20:58:36.520 回答
7

是的。

只有非常奇怪的运算符实现才会==使. 如果您使用的类具有如此奇怪的相等实现,那么在使用泛型类型参数检查 null 时,您会遇到更大的问题。x == nullReferenceEquals(x, null)

于 2013-09-25T21:00:41.487 回答
4

该文档告诉您,==无论实际类型T是什么,都会使用引用比较,即使它已经重载了==运算符。在许多情况下,这不是用户所期望的。

在 resharper 代码的情况下,它将变量与 null 进行比较,您希望将其作为参考比较,而不是值比较,因此文档警告您的是此处的正确行为。

但是,您可以通过编写类似这样的内容来使其更加明确,只是为了更清楚:

if(object.ReferenceEquals(type, null))//...
于 2013-09-25T21:00:06.850 回答
2

是的,通常可以假设这null是一个特殊情况,并且可以这样做==!=对其进行处理。这至少部分是由于覆盖的建议Equalsx.Equals(null)应该是false

如果您没有T : class约束,那将是另一回事,因为您会看到structs 和可为空struct的 s 的一些可能意外的行为(您可能想要这样做default(T)而不是在null那里)。

如果您想明确表示是的,您知道您正在比较对 的引用null,您可以随时使用object.ReferenceEquals(x, null)(不过,我只会使用==/ !=)。

于 2013-09-25T20:59:12.007 回答
1

我会说这没关系。

null有点特殊,因此您没有在两个参考变量之间进行实际比较,您只是确保参考变量不是空引用。

例如,将此与 SQL 进行比较。比较 ( a = b) 和空值检查 ( a is null) 的语法完全不同。指导原则是你应该避免第一个,但第二个是可以的。

于 2013-09-25T21:01:45.800 回答