比较两个对象

发布于 2024-10-20 13:44:32 字数 760 浏览 1 评论 0原文

使用 Object.Equals 会导致两个使用相同构造函数新创建的对象返回 false。这是为什么呢?我希望能够比较两个对象并查看它们是否相同,换句话说,我想做与上面相同的测试,但我希望能够在第一次测试中得到 true (因为这两个对象应该是相同的)。

如何在不为任何特定类构建自己的比较方法的情况下实现这一目标。

using System;
class Program
{
    static void Main(string[] args)
    {
        Object Obj1 = new Object();
        Object Obj2 = new Object();
        Console.WriteLine(Obj1.Equals(Obj2));
        Obj2 = Obj1;
        Console.WriteLine(Obj1.Equals(Obj2)); 
    }
}

/* This example produces the following output:
False
True
 */

附录:

Object o1 = new Object();
Object o2 = new Object();

o1.value1 = 1;
o2.value1 = 1;

//Now I want to compare o1 and o2 and see if they are equal
//Can I do this without building my own function?

Using Object.Equals results in a false with two newly created objects using the same constructor. Why is this? I want to be able to compare two objects and see if they are the same, in other words, I want to do the same test as above, but I want to be able to get a true on the first test (since the two objects should be identical).

How can I accomplish this without building my own compare method for any particular class.

using System;
class Program
{
    static void Main(string[] args)
    {
        Object Obj1 = new Object();
        Object Obj2 = new Object();
        Console.WriteLine(Obj1.Equals(Obj2));
        Obj2 = Obj1;
        Console.WriteLine(Obj1.Equals(Obj2)); 
    }
}

/* This example produces the following output:
False
True
 */

Addendum:

Object o1 = new Object();
Object o2 = new Object();

o1.value1 = 1;
o2.value1 = 1;

//Now I want to compare o1 and o2 and see if they are equal
//Can I do this without building my own function?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(8

自演自醉 2024-10-27 13:44:32

Object.Equals() 正在使用引用比较的相等性,只有当它是相同的对象引用时才会结果为 true。您可以为自己的从 Object 派生的类型重写此行为。

来自 MSDN:

Equals 的默认实现
支持引用相等
引用类型和按位相等
对于值类型。引用相等
表示对象引用
比较指的是同一个对象。
按位相等意味着对象
被比较的具有相同的二进制
代表。

请注意,派生类型可能
重写 Equals 方法以
落实价值平等。价值
相等是指比较对象
即使它们具有相同的值
有不同的二进制表示。
例如,考虑两个十进制
代表数字的对象
1.10 和 1.1000。 Decimal 对象不具有按位相等性,因为
他们有不同的二进制
陈述以解释
不同数量的尾随零。
但物品还是有其价值的
相等,因为数字 1.10 和
出于比较目的,1.1000 被认为是相等的,因为尾随
零是微不足道的。

Object.Equals() is using reference equality for comparing, which will only result in true if it's the same object reference. You can override this behavior for your own types that derive from Object.

From MSDN:

The default implementation of Equals
supports reference equality for
reference types, and bitwise equality
for value types. Reference equality
means the object references that are
compared refer to the same object.
Bitwise equality means the objects
that are compared have the same binary
representation.

Note that a derived type might
override the Equals method to
implement value equality. Value
equality means the compared objects
have the same value even though they
have different binary representations.
For example, consider two Decimal
objects that represent the numbers
1.10 and 1.1000. The Decimal objects do not have bitwise equality because
they have different binary
representations to account for the
different number of trailing zeroes.
However, the objects have value
equality because the numbers 1.10 and
1.1000 are considered equal for comparison purposes since the trailing
zeroes are insignificant.

云淡月浅 2024-10-27 13:44:32

当我做出这个答案时我很着急,这就是我重写我的答案的原因。

当您使用相同的数据创建同一个类两次时,equals 方法会检查两个对象的引用是否相等,它们仍然存储在内存中的不同位置,因此它们的引用不相等,并且 Equals 方法返回 false。

要检查类的值是否相等,您必须重写 Equals 方法,同时要使用 == 和 != 运算符,我们需要重载它们。

例如,字符串类会覆盖它,如果它不这样做,则会打印 false:

string test = "string";
string test2 = "string";
Console.WriteLine(test == test2);

示例:

// Example 1:
// Without overriding the Equals method:
Foo f1 = new Foo();
Foo f2 = new Foo();
f1.Name = "String";
f2.Name = "String";
bool fooEquals = f1 == f2; // False
f2.Name = "Test";
fooEquals f1 == f2; // False

// Example 2:
// With overriding the Equals method:
Foo f1 = new Foo();
Foo f2 = new Foo();
f1.Name = "String";
f2.Name = "String";
bool fooEquals = f1 == f2; // True
f2.Name = "Test";
fooEquals f1 == f2; // False

This is Foo in the first example:

public class Foo
{
    public string Name { get; set; }
}

This is Foo in the second example:

public class Foo
{
    public string Name { get; set; }

    public override bool Equals(object obj)
    {
        // If parameter is null return false.
        if (obj == null)
        {
            return false;
        }

        // If parameter cannot be cast to Point return false.
        Foo p = obj as Foo;
        if ((System.Object)p == null)
        {
            return false;
        }

        // Return true if the fields match:
        return (Name == p.Name);
    }

    public bool Equals(Foo p)
    {
        // If parameter is null return false:
        if ((object)p == null)
        {
            return false;
        }

        // Return true if the fields match:
        return (Name == p.Name);
    }

    public static bool operator ==(Foo f1, Foo f2)
    {
        return f1.Equals(f2);
    }

    public static bool operator !=(Foo f1, Foo f2)
    {
        return !f1.Equals(f2);
    }

    public override int GetHashCode()
    {
        return Name.GetHashCode();
    }
}

注意: 当覆盖 Equals 时或重载 ==/!=,Visual Studio 希望您重写 GetHashCode 函数。该函数对于 Foo 的每个实例都应该是唯一的,并且具有相同的值。

I was in a hurry when I made this answer, that's why I've rewritten my answer.

The equals method checks if references of two objects equal, when you create the same class twice with the same data, they're are still stored at different positions in memory, therefore their reference doesn't equal, and the Equals method returns false.

To check whenever the value of the classes equal you'll have to override the Equals method, also to make use of the == and != operators we'll need to overload those.

For example the string class overrides it, if it wouldn't do that this would print false:

string test = "string";
string test2 = "string";
Console.WriteLine(test == test2);

Examples:

// Example 1:
// Without overriding the Equals method:
Foo f1 = new Foo();
Foo f2 = new Foo();
f1.Name = "String";
f2.Name = "String";
bool fooEquals = f1 == f2; // False
f2.Name = "Test";
fooEquals f1 == f2; // False

// Example 2:
// With overriding the Equals method:
Foo f1 = new Foo();
Foo f2 = new Foo();
f1.Name = "String";
f2.Name = "String";
bool fooEquals = f1 == f2; // True
f2.Name = "Test";
fooEquals f1 == f2; // False

This is Foo in the first example:

public class Foo
{
    public string Name { get; set; }
}

This is Foo in the second example:

public class Foo
{
    public string Name { get; set; }

    public override bool Equals(object obj)
    {
        // If parameter is null return false.
        if (obj == null)
        {
            return false;
        }

        // If parameter cannot be cast to Point return false.
        Foo p = obj as Foo;
        if ((System.Object)p == null)
        {
            return false;
        }

        // Return true if the fields match:
        return (Name == p.Name);
    }

    public bool Equals(Foo p)
    {
        // If parameter is null return false:
        if ((object)p == null)
        {
            return false;
        }

        // Return true if the fields match:
        return (Name == p.Name);
    }

    public static bool operator ==(Foo f1, Foo f2)
    {
        return f1.Equals(f2);
    }

    public static bool operator !=(Foo f1, Foo f2)
    {
        return !f1.Equals(f2);
    }

    public override int GetHashCode()
    {
        return Name.GetHashCode();
    }
}

NOTE: When overriding Equals or overloading ==/!=, Visual Studio want you to override the GetHashCode function. That function should be unique for every instance of Foo, with the same values.

幸福丶如此 2024-10-27 13:44:32

大多数答案都是正确的,我只会提供更多细节:

从 System.Object 派生的类的任何实例(除了 System.ValueType 类之外)都是“引用”类。 “参考”类有两部分:实例的“核心”被放置在程序的内存中,称为“堆”,然后指向该内存地址的“引用”或“指针”被放置在堆栈中。有关堆栈和堆是什么以及为什么需要它们的更多信息,请参阅 MSDN 文档或计算机编程基本入门书。

在.NET中,引用类型的两个变量的相等性默认比较是比较变量存储的内存地址。这就是“引用相等”;如果两个变量指向相同的内存地址,则它们相等。如果没有,他们就不是。

对于“语义”或“结构”平等,需要更深入地了解每个变量的内存空间中的内容。一般情况下不能这样做;开发人员必须为他想要比较的每个类定义什么使他的类的两个实例在语义上相等。这是通过重写从 Object 类继承的 Equals() 方法来实现的(因此对所有 .NET 类都是通用的)。 Equals 重写通常具有以下结构:

public override bool Equals (object other)
{
    //Reference equality is still a simple and necessary check
    if(Object.ReferenceEquals(this, other)) return true;

    //Another simple check; the two objects should be the same type
    if(this.GetType() != other.GetType()) return false;

    //Now, compare members of the object that you want to use to determine
    //"semantic" equality. These members, if also reference types, must also
    //be "semantically" equal.

    if(this.Property1 == other.Property1 && this.FieldA == other.FieldA && ... )
       return true;

    return false;
}

实现 IComparable、IEquatable 和 IStructuralEquatable 接口向使用者提供当前类的作者具有相等或其他比较的自定义定义的线索。它们在某些情况下是必要的,但并非在所有情况下都是必要的。

Most of the answers are correct, I'll just give a little more detail:

Any instance of a class deriving from System.Object, except for those that are System.ValueType classes, is a "reference" class. A "reference" class has two parts; the "meat" of the instance is placed in the program's memory, called the "heap", and then a "reference" or "pointer" to that memory address is placed in the stack. For more information on what the stack and heap are and why they're necessary, consult the MSDN docs or a basic primer in computer programming.

In .NET, the default comparison of equality of two variables of a reference type is to compare the memory addresses stored by the variables. This is "reference equality"; if two variables point to the same memory address, they are equal. If not, they're not.

For "semantic" or "structural" equality, a deeper look at what lives in each variable's memory space is required. This can't be done in the general case; the developer must define, for each class he wishes to compare, what makes two instances of his class semantically equal. This is accomplished by overriding the Equals() method which is inherited from the Object class (and thus common to all .NET classes). An Equals override generally has the following structure:

public override bool Equals (object other)
{
    //Reference equality is still a simple and necessary check
    if(Object.ReferenceEquals(this, other)) return true;

    //Another simple check; the two objects should be the same type
    if(this.GetType() != other.GetType()) return false;

    //Now, compare members of the object that you want to use to determine
    //"semantic" equality. These members, if also reference types, must also
    //be "semantically" equal.

    if(this.Property1 == other.Property1 && this.FieldA == other.FieldA && ... )
       return true;

    return false;
}

Implementing the IComparable, IEquatable and IStructuralEquatable interfaces provide clues to consumers that the author of the current class has a custom definition of equality or other comparison. They are necessary in some cases, not in all.

々眼睛长脚气 2024-10-27 13:44:32

我相信你必须创建自己的比较方法,并实现 ICompare 接口

I believe you have to create your own compare method, and implement the ICompare interface

ι不睡觉的鱼゛ 2024-10-27 13:44:32

Object.Equals() 是引用相等。您必须构建自己的比较方法,无论是重写 equals,还是实现 IEqualityComparer,或任何其他比较接口。

Object.Equals() is reference equality. You must build your own comparison method, be it overriding equals, or implementing IEqualityComparer, or any of the other comparison interfaces.

享受孤独 2024-10-27 13:44:32

与按值比较的基元不同,使用对象的引用来比较对象。这经常困扰字符串新手,在很多语言中字符串都是对象,他们只是尝试使用原始比较来检查它们的相等性。

如果您确实希望能够使用 == 运算符进行比较,那么您可以 重载运算符

Objects are compared using the reference to the object, unlike primitives that are compared by value. This frequently plagues newbies with strings, which in a lot of languages are Objects and they simply try to check their equality using the primitive comparison.

If you really want to be able to compare using the == operator, then you can overload the operator.

情绪失控 2024-10-27 13:44:32

除了引用标识之外,object 类型绝对没有任何区别特征。如果您希望两个不同的 object 实例比较相等,只需实现您自己的比较器

class ObjectComparer : IEqualityComparer<object>
{
    public bool Equals(object x, object y)
    {
        if (x == null || y == null)
        {
            return false;
        }

        return x.GetType == typeof(object) && y.GetType() == typeof(object);
    }

    public int GetHashCode(object obj)
    {
        if (obj == null)
        {
            return 0;
        }

        if (obj.GetType() == typeof(object))
        {
            return 1; // I don't know, whatever.
        }

        return obj.GetHashCode();
    }
}

哦等等,这就是您想要做的。好吧,然后创建您自己的类型,使其按照您想要的方式运行:

sealed class SimpleObject()
{
    // No characteristics, all instances equal.
    public override bool Equals(object obj)
    {
        return obj is SimpleObject;
    }

    public override int GetHashCode()
    {
        return 0;
    }
}

您不能只更改 object 类型本身。

The object type has absolutely no distinguishing characteristics other than reference identity. If you want two distinct object instances to compare equal, just implement your own comparer:

class ObjectComparer : IEqualityComparer<object>
{
    public bool Equals(object x, object y)
    {
        if (x == null || y == null)
        {
            return false;
        }

        return x.GetType == typeof(object) && y.GetType() == typeof(object);
    }

    public int GetHashCode(object obj)
    {
        if (obj == null)
        {
            return 0;
        }

        if (obj.GetType() == typeof(object))
        {
            return 1; // I don't know, whatever.
        }

        return obj.GetHashCode();
    }
}

Oh wait, that's what you don't want to do. Well, then make your own type that behaves the way you want:

sealed class SimpleObject()
{
    // No characteristics, all instances equal.
    public override bool Equals(object obj)
    {
        return obj is SimpleObject;
    }

    public override int GetHashCode()
    {
        return 0;
    }
}

You can't just change the object type itself.

傲影 2024-10-27 13:44:32

对象类的 equals 方法比较两个引用。由于您正在创建一个新对象,因此它们永远不会相等。

The equals method for the object class compares the two references. Since you are creating a new object they will never be equal.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文