== 和 String.Equals 方法之间有一个微妙但非常重要的区别:
class Program
{
static void Main(string[] args)
{
CheckEquality("a", "a");
Console.WriteLine("----------");
CheckEquality("a", "ba".Substring(1));
}
static void CheckEquality<T>(T value1, T value2) where T : class
{
Console.WriteLine("value1: {0}", value1);
Console.WriteLine("value2: {0}", value2);
Console.WriteLine("value1 == value2: {0}", value1 == value2);
Console.WriteLine("value1.Equals(value2): {0}", value1.Equals(value2));
if (typeof(T).IsEquivalentTo(typeof(string)))
{
string string1 = (string)(object)value1;
string string2 = (string)(object)value2;
Console.WriteLine("string1 == string2: {0}", string1 == string2);
}
}
}
产生这个输出:
value1: a
value2: a
value1 == value2: True
value1.Equals(value2): True
string1 == string2: True
----------
value1: a
value2: a
value1 == value2: False
value1.Equals(value2): True
string1 == string2: True
您可以看到 == 运算符将 false 返回到两个明显相等的字符串。为什么?因为在泛型方法中使用的 == 运算符被解析为由 System.Object 定义的 op_equal 方法(该方法在编译时具有 T 的唯一保证),这意味着它是引用相等而不是值相等。
当您有两个明确键入为 System.String 的值时,== 具有值相等语义,因为编译器将 == 解析为 System.String.op_equal 而不是 System.Object.op_equal。
所以为了安全起见,我几乎总是使用 String.Equals 来代替我总是得到我想要的值相等语义。
如果其中一个值为 null,为了避免 NullReferenceExceptions,我总是使用 static String.Equals 方法:
bool true = String.Equals("a", "ba".Substring(1));