开发者

Comparing Two Objects

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 Obje开发者_运维知识库ct();
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?


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.


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.


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.


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


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.


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.


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.


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

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜