我刚刚看到一段使用if(!(a == b))
而不是常见的if(a != b)
的代码,这在C#中是否有区别?
using System;
class Test
{
// All this code is awful. PURELY FOR DEMONSTRATION PURPOSES.
public static bool operator==(Test lhs, Test rhs) => true;
public static bool operator!=(Test lhs, Test rhs) => true;
public override bool Equals(object other) => true;
public override int GetHashCode() => 0;
static void Main()
{
Test a = null;
Test b = null;
Console.WriteLine(a != b); // True
Console.WriteLine(!(a == b)); // False
}
}
在绝大多数情况下,a != b
和!(a == b)
的行为完全相同,而a != b
几乎总是更清晰明了的选择。但值得注意的是它们可能会有所不同。
甚至可以变得更加病态 - a != b
和!(a == b)
甚至可能具有不同的类型。例如:
using System;
class Test
{
// All this code is awful. PURELY FOR DEMONSTRATION PURPOSES.
public static Test operator==(Test lhs, Test rhs) => new Test();
public static Test operator!=(Test lhs, Test rhs) => new Test();
public static string operator!(Test lhs) => "Negated";
public override string ToString() => "Not negated";
public override bool Equals(object other) => true;
public override int GetHashCode() => 0;
static void Main()
{
Test a = null;
Test b = null;
Console.WriteLine(a != b); // "Not negated"
Console.WriteLine(!(a == b)); // "Negated"
}
}
这里a != b
的类型是Test
,但是!(a == b)
的类型是string
。是的,这很糟糕,你在现实生活中不太可能遇到它 - 但这是C#编译器需要了解的一种情况。
!
和 ==
和 !=
被重载,那么第一个调用前两个操作符,第二个调用第三个操作符。它们被允许做非常不同的事情,尽管这样做是愚蠢的。==
和!=
操作符;例如,你可以说bool operator !=(C x, C y) => !(x == y);
在这种情况下,x != y
将会无限递归,这与调用 !(x == y)
是完全不同的!从逻辑和概念上讲,它们没有区别,但是由于运算符可以被重载,所以在实现上可能会有差异。
这突显了编程中的一个普遍点,即任何方法、运算符、属性或其他内容都应该准确地做“标签上标明的事情”。理想情况下,不应该有任何意外、不一致或隐藏在实现中的意外行为。
!=
,除非实际代码比这个更复杂。 - Robert Harvey