【问题标题】:Why is the C# != operator comparing value types by reference?为什么 C# != 运算符通过引用比较值类型?
【发布时间】:2013-06-03 16:46:03
【问题描述】:

我有以下返回错误的代码:

 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"}

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

【问题讨论】:

  • 你能发布两个数据行的全部内容吗?在你的例子中 34 != 34 是假的,所以它不能返回假,因此问题将出在其他值上。
  • 嗯,这就是我的想法,但显然 GetType()==Int64 根据答案不是“正确的”。类型实际上是对象。

标签: c# operators


【解决方案1】:

当你这样做时:

(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");

调试输出:
等于=真

【讨论】:

    【解决方案2】:

    由于DataRow.Item 索引器的返回类型为Object,因此任何值类型在返回之前都需要为boxed。随后,您的相等比较是在包装您的值的对象实例上执行的,而不是在值本身上。要执行值比较,您需要通过将值转换回正确的类型来拆箱,或者使用多态 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
    

    编辑:您需要区分对象的运行时类型和它声明的类型。装箱时,您的项目的声明类型为object(根据DataRow.Item 索引器的返回类型),但运行时类型仍为long(或Int64)。运算符,例如!=,根据声明的类型解析,而在派生类中被覆盖的实例方法将根据运行时类型调用。这就是Equals 在上述情况下正常工作的原因。

    【讨论】:

    • 为什么GetType() 不返回对象呢?
    • @rism 看看this 和this
    猜你喜欢
    • 1970-01-01
    • 2012-10-17
    • 1970-01-01
    • 1970-01-01
    • 2018-09-23
    • 1970-01-01
    • 2013-11-08
    • 2021-11-07
    • 2023-03-03
    相关资源
    最近更新 更多