为什么c# !=操作符通过引用比较值类型?
本文关键字:比较 引用 类型 操作符 为什么 | 更新日期: 2023-09-27 18:17:34
我有以下返回false的代码:
private static bool AreRowsEqual(string[] fieldNames, DataRow row1, DataRow row2)
{
for (var i = 0; i <= fieldNames.Length - 1; i++)
{
if (row1[fieldNames[i]] != row2[fieldNames[i]])
{
return false;
}
}
return true;
}
这是令人惊讶的,因为只有一个类型为long的字段被比较,并且每个字段的值与每个直接窗口输出相匹配:
?row1[fieldNames[i]];
34
?row2[fieldNames[i]];
34
?row1[fieldNames[i]].GetType();
{Name = "Int64" FullName = "System.Int64"}
[System.RuntimeType]: {Name = "Int64" FullName = "System.Int64"}
? row2[fieldNames[i]].GetType();
{Name = "Int64" FullName = "System.Int64"}
[System.RuntimeType]: {Name = "Int64" FullName = "System.Int64"}
我在这里忽略了什么?当比较值上的整数时,我"到处"使用!=和==。
当你这样做的时候:
(row1[fieldNames[i]] != row2[fieldNames[i]])
row[x]
给出一个object
,参见http://msdn.microsoft.com/en-us/library/146h6tk5.aspx
如果比较对象与==
,则比较引用。
你必须转换成他们的原始数据类型或与obj.Equals(obj2)
比较
object a = 2;
object b = 2;
if (a == b)
Debug.WriteLine("== = true");
if (a.Equals(b))
Debug.WriteLine("equals = true");
调试输出:
= true
由于DataRow.Item
索引器的返回类型为Object
,因此任何值类型都需要在返回之前进行装箱。随后,对包装值的对象实例执行相等比较,而不是对值本身执行相等比较。要执行值比较,您需要通过将值转换回其适当的类型来打开您的值,或者使用多态Equals
方法。
int i1 = 34;
int i2 = 34;
Console.WriteLine(i1 == i2); // gives true
object o1 = i1;
object o2 = i2;
Console.WriteLine(o1 == o2); // gives false
Console.WriteLine((int)o1 == (int)o2); // gives true
Console.WriteLine(o1.Equals(o2)); // gives true
Edit:您需要区分对象的运行时类型和它声明的类型。装箱后,项目的声明类型为object
(根据DataRow.Item
索引器的返回类型),但运行时类型仍为long
(或Int64
)。操作符(如!=
)将根据声明的类型进行解析,而在派生类中被覆盖的实例方法将根据运行时类型进行调用。这就是为什么Equals
在上述情况下可以正常工作。