Reputation: 747
If I have a object like:
public class Person
{
public int id {get;set;}
public string name {get;set;}
}
And I want the behavior:
Person a = new Person();
Person b = new Person();
a == b;
and that a == b returns true, do I have to override the Object.Equals() method? or is there some other way of doing it without overriding the Equals method?
EDIT
I want to compare data, as I want to know if a external method that I call returns a new object or a object with different data than a new object
Upvotes: 17
Views: 41378
Reputation: 164
You can compere using JsonSerializer, where all the values types and the values types holding by refrences types are equals
this is as a method
using System.Text.Json;
public bool Compare<T> (T element1, T element2)
{
return (JsonSerializer.Serialize(element1) == JsonSerializer.Serialize(element2));
}
this is as extension
using System.Text.Json;
static class Extension
{
static bool Compare<T>(this T element1, T element2)
{
return (JsonSerializer.Serialize(element1) == JsonSerializer.Serialize(element2));
}
}
Upvotes: 0
Reputation: 1194
If you want you can write an extention methode like this (make a new class like this) :
public static class Extensions
{
public static bool IsEqual<T>(this T objA, T objB)
{
foreach (var item in objA.GetType().GetProperties())
{
if (item.GetValue(objA).ToString() != item.GetValue(objB).ToString())
return false;
}
return true;
}
}
}
Then you can use this extention methode something like this :
Person a = new Person { id = 1, name = "person1" };
Person b = new Person { id = 1, name = "person1" };
....
if ( a.IsEqual<Person>(b)) // this returns true ;)
{
do something ...
}
else
{
do something else ...
}
....
Enjoy it.
Upvotes: 3
Reputation: 463
In C# 9.0 and above, there is a new type called record
whose equality is value-based. So you can define it like:
public record Person
{
public string LastName { get; }
public string FirstName { get; }
public Person(string first, string last) => (FirstName, LastName) = (first, last);
}
Then you can use
var bill1 = new Person("Bill", "Wagner");
var bill2 = new Person("Bill", "Wagner");
Console.WriteLine(bill1 == bill2); // true
Reference: https://learn.microsoft.com/en-us/dotnet/csharp/whats-new/csharp-9#record-types
Upvotes: 3
Reputation: 460058
You want to overload the ==
operator. Therefore you should also override Equals
first. If you override Equals
you should always also override GetHashCode
. If you overload the ==
operator you must also overload the !=
operator:
public class Person
{
public int id {get;set;}
public string name {get;set;}
public override bool Equals(object obj)
{
Person p2 = obj as Person;
if (object.ReferenceEquals(null, p2)) return false;
return id == p2.id;
}
public static bool operator ==(Person p1, Person p2)
{
if (object.ReferenceEquals(null, p1))
return object.ReferenceEquals(null, p2);
else if (object.ReferenceEquals(null, p2))
return false;
return p1.Equals(p2);
}
public static bool operator !=(Person p1, Person p2)
{
if (object.ReferenceEquals(null, p1))
return !object.ReferenceEquals(null, p2);
else if (object.ReferenceEquals(null, p2))
return true;
return !p1.Equals(p2);
}
public override int GetHashCode()
{
return id ;
}
}
Now this compares values (the id
) instead of only references:
Person p1 = new Person { id = 1, name = "Jeff" };
Person p2 = new Person { id = 2, name = "Tim" };
bool equalPersons = p1 == p2; // false
Person p3 = new Person { id = 1, name = "Jeff 2.0" }; // same id -> equal
equalPersons = p1 == p3; // true
MSDN: Guidelines for Implementing Equals and the Equality Operator (==)
Upvotes: 2
Reputation: 14432
There are a couple of ways you can do this. By default Equals()
and ==
check for reference equality, meaning:
Person a = new Person();
Person b = a:
a.Equals(b); //true
a == b; //true
And therefore, the objects are not compared for value equality, meaning:
Person a = new Person { id = 1, name = "person1" };
Person b = new Person { id = 1, name = "person1" };
a.Equals(b); //false
a == b; //false
To compare objects for their values you can override the Equals()
and GetHashcode()
methods, like this:
public override bool Equals(System.Object obj)
{
if (obj == null)
return false;
Person p = obj as Person;
if ((System.Object)p == null)
return false;
return (id == p.id) && (name == p.name);
}
public bool Equals(Person p)
{
if ((object)p == null)
return false;
return (id == p.id) && (name == p.name);
}
public override int GetHashCode()
{
return id.GetHashCode() ^ name.GetHashCode();
}
Now you will see other results when comparing:
Person a = new Person { id = 1, name = "person1" };
Person b = new Person { id = 1, name = "person1" };
Person c = a;
a == b; //false
a == c; //true
a.Equals(b); //true
a.Equals(c); //true
The ==
operator is not overridden and therefore still does reference comparison. This can be solved by overloading it as well as the !=
operator:
public static bool operator ==(Person a, Person b)
{
if (System.Object.ReferenceEquals(a, b))
return true;
if ((object)a == null || (object)b == null)
return false;
return a.id == b.id && a.name == b.name;
}
public static bool operator !=(Person a, Person b)
{
return !(a == b);
}
Now running the checks results in following:
Person a = new Person { id = 1, name = "person1" };
Person b = new Person { id = 1, name = "person1" };
Person c = a;
a == b; //true
a == c; //true
a.Equals(b); //true
a.Equals(c); //true
More reading:
Upvotes: 39
Reputation: 82096
This all depends on what you are trying to compare, by default Equals
will compare by reference therefore
a == b
in your example will always be false
. However, if you did something like
Person a = new Person();
Person b = a;
Then a == b
would be true
because both a
and b
are using the same reference.
do i have to override the Object.Equals() method?
Overriding Equals and GetHashCode is the recommended approach, however, (for arguments sake) it's not the only way. You could, for example, override the ==
operator and do your comparison in there. However, there are limitations with going down that route alone.
Most comparison checks, if not all, will use Equals
internally which is why it's the preferred approach. See Guidelines for Implementing Equals and the Equality Operator (==).
Upvotes: 2
Reputation: 1481
Yes. You want to compare to objects of Person, you need to override equals and hashcode method from Object class as by default reference check (==) is done through equals method.
Assuming two Persons with same name and id can only be considered equal use both of these properties in equals and hashcode method.
Generating equals and hashcode has beocme easier with the Java IDE's provided. U can try below code.
public class Person {
private int id;
private String name;
// id getters and setters
// name getters and setters
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + id;
result = prime * result + ((name == null) ? 0 : name.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Person other = (Person) obj;
if (id != other.id)
return false;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
return true;
}
}
Upvotes: 0
Reputation: 2163
Suppose Test is Class
Test a = new Test() { Num = 1, Str = "Hi" };
Test b = new Test() { Num = 1, Str = "Hi" };
bool areEqual = System.Object.ReferenceEquals(a, b);
Upvotes: -2