1.==
运算符
==
是一个运算符,用于比较两个值是否相等。对于值类型(如 int
、float
、double
等),==
直接比较两个值是否相同。对于引用类型(如类和数组),==
比较两个引用是否指向内存中的同一个对象。
2.Equal函数
C#中所有类型(自定义的也一样)都继承自System.Object类,因此所有类型都有Equal这个比较方法,Equal一般会来自两个地方
第一个地方
public virtual bool Equals(object obj)
//自己可以重写的噢
这是从 System.Object
继承而来的方法,它接受一个 object
类型的参数。默认情况下,这个方法执行引用相等性检查,即它检查两个对象是否引用同一个对象实例。
第二个地方
public bool Equals(T other)
这是一个泛型重载,它接受一个与当前对象类型相同的参数。这个重载通常在实现了 IEquatable<T>
接口的类中被重写,用于执行值相等性检查。
如Int类型的:(override是重写,这个函数Equals(object obj)它还可以重写的)
对于引用类型,Equals(object obj)
默认比较的是引用,即检查两个对象是否是同一个实例。对于值类型,它比较的是值。
3.string、结构体struct比较
对于 string、
结构体struct类型,使用 ==
运算符和 Equals
方法都是进行值比较,它们的行为是一致的。
4.不同
==运算符可以处理null,而Object.Equals
操作变量为null时会报错,如下
Ap re = null;
Ap res = new Ap();if(re.Equals(res))
{Console.WriteLine("相同");
}未经处理的异常: System.NullReferenceException: 未将对象引用设置到对象的实例。
因此,使用Equals比较时请养成好习惯,记得判空
Ap re = null;
Ap res = new Ap();if(re != null)
{if(re.Equals(res)){Console.WriteLine("相同");}
}
参考:
比较 .NET 中的字符串 - .NET | Microsoft Learn
C# 中 == 和 .Equals() 之间的区别 - 误会馋 - 博客园(强烈推荐一读)
纠错 1
int x = 2;
int y = 2;Console.WriteLine(x == y); //True
Console.WriteLine(x.Equals(y)); //TrueConsole.WriteLine(x == 2.0); //True
Console.WriteLine(x.Equals(2.0)); //False
Console.WriteLine(x == 2.0); //True
这里 ==
操作符比较 int
类型的 x
和 double
类型的字面量 2.0
。在C#中,int
类型可以隐式转换为 double
类型,这里发生了隐式转换,因此 2
被转换为 2.0
,然后比较这两个值是否相等,结果是 True
。
Console.WriteLine(x.Equals(2.0)); //False
这里 Equals()
方法的行为与 ==
操作符不同。Equals()
方法在没有被重写的情况下,对于 int
类型的 x
和 double
类型的 2.0
,会返回 False
,因为 Equals()
方法默认比较的是引用类型的引用是否相等,而 int
和 double
是不同的类型,它们在内存中的存储和表示也不同。即使它们的数值相同,Equals()
方法也会因为类型不匹配而返回 False。
如图可以看到编译器这里提示调用的函数,前一个Equal参数是同类型的int,这里的Equal参数类型时object
误区 2
在 C# 中,如果字符串的内容相同,那么认定它们指向相同的内存位置,这里是很多人容易犯错的误区,认为出现的字符串都是同一个对象,即堆区同一个地址;大部分情况是,因为string
类型在C#中有一个特殊的内部机制,称为字符串内部缓存。对于字面量字符串或者在编译时已知的字符串,编译器会尝试重用相同的字符串对象,这意味着即使它们在代码中被多次声明,它们实际上可能指向同一个对象。
有同学可能对字面量不理解,字面量是直接在代码中给出的值,而不是通过变量名或计算得到的
"ni hao" //这是字面量,直接展示的10 //也是字面量、int a = 9;//a是变量,9是字面量
因此会有如下的代码对比
public class Ap{public string a;}Ap ap1 = new Ap();ap1.a = "we";Ap ap2 = new Ap();ap2.a = "we";Console.WriteLine(ap1.a == ap2.a);//TrueConsole.WriteLine(ap1.a.Equals(ap2.a));//Truestring str1 = "Compare";string str2 = "Compare";Console.WriteLine(str1 == str2);//TrueConsole.WriteLine(str1.CompareTo(str2));//0Console.WriteLine(String.Compare(str1, str2));//0Console.WriteLine(str1.Equals(str2));//TrueConsole.WriteLine(String.Equals(str1, str2));//TrueConsole.WriteLine(Object.ReferenceEquals(str1, str2));//True
字面量的字符串都是相同的,因为引用了同一个地址,但是这并不适用于通过 new
关键字显式创建的字符串对象,因为显式创建的字符串对象总是不同的实例。
如下:
object str1 = new string(new char[] { 't', 'u', 't', 'o', 'r', 'i', 'a', 'l' });object str2 = new string(new char[] { 't', 'u', 't', 'o', 'r', 'i', 'a', 'l' });Console.WriteLine(str1 == str2); //FalseConsole.WriteLine(str1.Equals(str2)); //Truestring str3 = new string(new char[] { 't', 'u', 't', 'o', 'r', 'i', 'a', 'l' });string str4 = new string(new char[] { 't', 'u', 't', 'o', 'r', 'i', 'a', 'l' });Console.WriteLine(str3 == str4); //TrueConsole.WriteLine(str3.Equals(str4)); //True
Console.WriteLine(str1 == str2); //False
这里使用 ==
操作符比较 str1
和 str2
。由于 str1
和 str2
是通过 new string(new char[] {...})
创建的两个不同的对象实例,即使它们的内容相同,它们在内存中的地址也是不同的。因此,==
操作符返回 False
,因为它比较的是对象的引用。
Console.WriteLine(str1.Equals(str2)); //True
Equals
方法在 string
类型中被重写,所以父类object对象调用的是子类string重写后的String.Equals(object obj)方法,该方法比较的同样是内容而非引用
。
我们之前说过无论是==还是Equal在比较字符串时总是值比较,看到str3和str4比较,因此值相等自然就相等。