C# 中 String 类型比较
对象的比较
-
操作比较的是两个变量的值是否相等。对于引用型变量来说其值就是堆地址,因此表示的是是否指向了同一堆对象空间。
-
操作表示的两个变量是否是对同一个对象的引用,即堆中的内容是否相同
-
值类型是从
System.ValueType
派生的,该类型派生自System.Object
。但是System.ValueType
重写了
而对其他对象(引用类型),只有指针指向同一堆空间地址 Equals
才会返回 True
```csharp
class Program
{
static void Main(string[] args) {
var x = new P { I = 1 };
var y = new P { I = 1 };
var z = x;
Console.WriteLine(x.Equals(y)); // False
Console.WriteLine(x.Equals(z)); // True
var a = new Q { I = 1 };
var b = new Q { I = 1 };
Console.WriteLine(a.Equals(b)); // True
}
}
class P
{
public int I { get; set; }
}
struct Q
{
public int I { get; set; }
}
```
String 的特殊处理
String
对 Equals
的特殊处理(重写 Equals
和 ==
方法等等)使得 String
更类似于值类型
在一般用于都是 string
的比较时,Equals
和 ==
表现相同
如以下代码:
string a = new string(new char[] { 'h', 'e', 'l', 'l', 'o' });
string b = new string(new char[] { 'h', 'e', 'l', 'l', 'o' });
//a 和 b 通过 new 操作符开辟了两个内存空间,因此是不同的对象
Console.WriteLine(a == b); // True
Console.WriteLine(a.Equals(b)); // True
// 由于 String 重写了 Equals 和 == 方法,实际上比较的是 a 和 b 的内容而不是堆地址
object oa = a;
object ob = b;
Console.WriteLine(oa == ob); // False
// 调用的是 Object 的 == 比较,因此是比较的 a 和 b 两个对象的堆地址,所以结果是 False
Console.WriteLine(oa.Equals(ob)); // True
// 由于多态性:Equals 是一个 Virtual 方法,其行为准则遵循基本语法,
// 由于父类的引用可以指向子类的对象,而运行期的方法调用都是和具体的对象确切类型绑定的,
// 因此调用 object 的 Equals 方法其实是调用子类 String 的 Equals 方法,
// 比较的是 a 和 b 的内容,所以结果是 True
a = "hello";
b = "hello"; // 注意和 new 并不相同
Console.WriteLine(a == b); // True
Console.WriteLine(a.Equals(b)); // True
oa = a;
ob = b;
Console.WriteLine(oa == ob); // True
Console.WriteLine(oa.Equals(ob)); // True
// 两个都相等是因为系统并没有给字符串 b 分配内存,
// 只是将 "hello" 指向了b, 所以 a 和 b 指向的是同一个字符串对象,
// 可以看做字符串在这种赋值的情况下做了内存的优化
string c = "hello";
object d = "hello";
Console.WriteLine(c.Equals(d)); // True
Console.WriteLine(d.Equals(c)); // True
Console.WriteLine(c == d); // True
// 如上所说的原因,a 和 b 指向的同一字符串对象
string e = new string(new char[] { 'h', 'e', 'l', 'l', 'o' });
object f = new string(new char[] { 'h', 'e', 'l', 'l', 'o' });
Console.WriteLine(e == f); // False
Console.WriteLine(e.Equals(f)); // True
Console.WriteLine(f.Equals(e)); // True
// 调用了 String 的 Equals
晕了没?
这些都不重要 :)
重要的是记住在比较对象时,尽量将两边转换为同一类型比较,避免掉进隐式转换的坑里
- posted on 2014-02-21 17:18
- C#