为什么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"}

我在这里忽略了什么?当比较值上的整数时,我"到处"使用!=和==。

为什么c# !=操作符通过引用比较值类型?

当你这样做的时候:

(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在上述情况下可以正常工作。