2

I have written a piece of code to check for Object Equality. I took refrence from one of the question in stack overflow itself. Now this code is giving true even if we have two different objects. Can someone explain why?

using System; namespace ConsolePractice { public class Test { public int Value { get; set; } public string String1 { get; set; } public string String2 { get; set; } public override int GetHashCode() { int hash = 19; hash = hash * 31 + Value; hash = hash * 31 + String1.SafeGetHashCode(); hash = hash * 31 + String2.SafeGetHashCode(); return hash; } public override bool Equals(object obj) { Test test = obj as Test; if (obj == null) { return false; } return Value == test.Value && String1 == test.String1 && String2 == test.String2; } } class Demo { static void Main() { Test p1 = new Test { Value = 10, String1 = "Test1", String2 = "Test2" }; Test p2 = new Test { Value = 10, String1 = "Test1", String2 = "Test2" }; bool areEqual = p1.Equals(p2); Console.WriteLine(areEqual.ToString()); Console.ReadLine(); } } } 

and in my UtilityClass

 static class utility { public static int SafeGetHashCode<T>(this T value) where T : class { return value == null ? 0 : value.GetHashCode(); } } 

After no success,i tried below code which also return true. What blunder am I doing here?Please help

using System; using System.Collections.Generic; class ThingEqualityComparer : IEqualityComparer<Thing> { public bool Equals(Thing x, Thing y) { if (x == null || y == null) return false; return (x.Id == y.Id && x.Name == y.Name); } public int GetHashCode(Thing obj) { return obj.GetHashCode(); } } public class Thing { public int Id { get; set; } public string Name { get; set; } } class Demo { static void Main() { Thing p1 = new Thing { Id = 10, Name = "Test1", }; Thing p2 = new Thing { Id = 10, Name = "Test1", }; var comparer = new ThingEqualityComparer(); Console.WriteLine(comparer.Equals(p1, p2)); Console.ReadLine(); } } 
3
  • 2
    Why do you not expect this to return true? Commented Aug 10, 2015 at 13:31
  • I think Test test = obj as Test; if (obj == null) should have been Test test = obj as Test; if (test == null) Commented Aug 10, 2015 at 13:31
  • @JonHanna-Because These are different objects .I believe we need to override Equals for value equality and check every field.here two objects are different,is it not supposed to give false? Commented Aug 10, 2015 at 13:36

1 Answer 1

3

You override Equals() and GetHashCode() to define what "equals" means in a given context.

Your Equals of:

Test test = obj as Test; if (obj == null) { return false; } return Value == test.Value && String1 == test.String1 && String2 == test.String2; 

Has a bug in that it should be if(test == null) return false; but otherwise it says "two Test objects are the same if they have the same Value, String1 and String2, otherwise they are not. Your GetHashCode() is consistent with that.

As such, it's not a bug to have the code return true:

Now this code is giving true even if we have two different objects.

Yes, two different equal objects.

If you want Equals and GetHashCode() to tell you whether they are the same object or not (that is, for an object of a class to be equal only to itself) then don't override Equals and GetHashCode at all; stay with the default behaviour.

Sign up to request clarification or add additional context in comments.

6 Comments

Got you point Sir..Just one more detail-If I need have one object(say o1) and other refrence (r1) to that object o1(r1=o1),then i can check this by default Equals..So why we have AS operator and same by Icomaprarer interface?That too does same thing right?Please forgive my confusion
as gives us a reference of a different type: Say object r1 = "abc" then string r2 = r1 as string means r2 is the same as r1 but as a string, while Uri r3 = r1 as Uri means r3 is null because r1 wasn't a Uri so this couldn't work. IComparer lets us compare objects in an order. IEqualityComparer lets us set different rules for equality than those set by the Equals override, should we have a special case. E.g. string has an Equals that returns true if two strings are exactly the same characters in same order but there are IEqualityComparers for case-insensitive etc
ReferenceEquals lets us tell if two equal objects are actually the same object or not. (Doing a matching GetHashCode() for that is tricky. Luckily it's rarely necessary but nuget.org/packages/AisA can be used in the very rare cases where we care).
@asawyer thanks a lot.IS operator also comapres two objects.Why cant we use this one.This is last piece of my confusion.
is also does not compare two objects. It tells use if an object is of a type; "abc" is string returns true, "abc" is int returns false. "abc" is "abc" (comparing two objects) does not compile and is not allowed. T y = x as T is the much the same as T y = (x is T) ? (T)x : null but only checks the type once.
|

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.