相等运算符 - 测试两个对象是否相等
==
(相等) 和 !=
(不等) 运算符检查其操作数是否相等。 当内容相等时,值类型相等。 当两个变量引用同一存储时,引用类型相等。
相等运算符 ==
如果操作数相等,等于运算符 ==
返回 true
,否则返回 false
。
值类型的相等性
如果内置值类型的值相等,则其操作数相等:
int a = 1 + 2 + 3;
int b = 6;
Console.WriteLine(a == b); // output: True
char c1 = 'a';
char c2 = 'A';
Console.WriteLine(c1 == c2); // output: False
Console.WriteLine(c1 == char.ToLower(c2)); // output: True
注意
对于 ==
、<
、>
、<=
和 >=
运算符,如果任何操作数不是数字(Double.NaN 或 Single.NaN),则运算的结果为 false
。 这意味着 NaN
值不大于、小于或等于任何其他 double
(或 float
)值,包括 NaN
。 有关更多信息和示例,请参阅 Double.NaN 或 Single.NaN 参考文章。
如果基本整数类型的相应值相等,则相同枚举类型的两个操作数相等。
用户定义的 struct 类型默认情况下不支持 ==
运算符。 要支持 ==
运算符,用户定义的结构必须重载它。
==
和 !=
运算符由 C# 元组支持。 有关详细信息,请参阅元组类型一文的元组相等部分。
引用类型的相等性
默认情况下,如果两个非记录引用类型操作符引用同一对象,则这两个操作符相等:
public class ReferenceTypesEquality
{
public class MyClass
{
private int id;
public MyClass(int id) => this.id = id;
}
public static void Main()
{
var a = new MyClass(1);
var b = new MyClass(1);
var c = a;
Console.WriteLine(a == b); // output: False
Console.WriteLine(a == c); // output: True
}
}
如示例所示,默认情况下,用户定义的引用类型支持 ==
运算符。 但是,引用类型可重载 ==
运算符。 如果引用类型重载 ==
运算符,使用 Object.ReferenceEquals 方法来检查该类型的两个引用是否引用同一对象。
记录类型相等性
记录类型支持 ==
和 !=
运算符,这些运算符默认提供值相等性语义。 也就是说,当两个记录操作数都是 null
所有字段的对应值或自动实现的属性相等时,两个记录操作数是相等的。
public class RecordTypesEquality
{
public record Point(int X, int Y, string Name);
public record TaggedNumber(int Number, List<string> Tags);
public static void Main()
{
var p1 = new Point(2, 3, "A");
var p2 = new Point(1, 3, "B");
var p3 = new Point(2, 3, "A");
Console.WriteLine(p1 == p2); // output: False
Console.WriteLine(p1 == p3); // output: True
var n1 = new TaggedNumber(2, new List<string>() { "A" });
var n2 = new TaggedNumber(2, new List<string>() { "A" });
Console.WriteLine(n1 == n2); // output: False
}
}
如前面的示例所示,对于非记录引用类型成员,比较的是它们的引用值,而不是所引用的实例。
字符串相等性
如果两个字符串均为 null
或者两个字符串实例具有相等长度且在每个字符位置有相同字符,则这两个字符串操作数相等:
string s1 = "hello!";
string s2 = "HeLLo!";
Console.WriteLine(s1 == s2.ToLower()); // output: True
string s3 = "Hello!";
Console.WriteLine(s1 == s3); // output: False
字符串相等比较是区分大小写的序号比较。 有关字符串比较的详细信息,请参阅如何在 C# 中比较字符串。
委托相等
若两个运行时间类型相同的委托操作数均为 null
,或其调用列表长度系统且在每个位置具有相同的条目,则二者相等:
Action a = () => Console.WriteLine("a");
Action b = a + a;
Action c = a + a;
Console.WriteLine(object.ReferenceEquals(b, c)); // output: False
Console.WriteLine(b == c); // output: True
有关详细信息,请参阅 C# 语言规范中的委托相等运算符部分。
通过计算语义上相同的 Lambda 表达式生成的委托不相等,如以下示例所示:
Action a = () => Console.WriteLine("a");
Action b = () => Console.WriteLine("a");
Console.WriteLine(a == b); // output: False
Console.WriteLine(a + b == a + b); // output: True
Console.WriteLine(b + a == a + b); // output: False
不等运算符 !=
如果操作数不相等,不等于运算符 !=
返回 true
,否则返回 false
。 对于内置类型的操作数,表达式 x != y
生成与表达式 !(x == y)
相同的结果。 有关类型相等性的更多信息,请参阅相等运算符部分。
下面的示例演示 !=
运算符的用法:
int a = 1 + 1 + 2 + 3;
int b = 6;
Console.WriteLine(a != b); // output: True
string s1 = "Hello";
string s2 = "Hello";
Console.WriteLine(s1 != s2); // output: False
object o1 = 1;
object o2 = 1;
Console.WriteLine(o1 != o2); // output: True
运算符可重载性
用户定义类型可以重载==
和 !=
运算符。 如果某类型重载这两个运算符之一,它还必须重载另一个运算符。
记录类型不能显式重载 ==
和 !=
运算符。 如果需要更改记录类型 T
的 ==
和 !=
运算符的行为,请使用以下签名实现 IEquatable<T>.Equals 方法:
public virtual bool Equals(T? other);
C# 语言规范
有关详细信息,请参阅 C# 语言规范中的关系和类型测试运算符部分。
有关记录类型相等性的详细信息,请参阅记录功能建议附注中的相等性成员部分。