0

I have an Object called User. Here's my class:

public class User
{
  public string Name { get; set; }
  public string IdNumber { get; set; }
  public string OrgName { get; set; }
  public string AcctCode { get; set; }
}

I create TWO objects that are exactly the same.

I want to see if their Equal, however, I get False back.

User user1 = new User()
{
  Name = "Test User",
  IdNumber = "1000354",
  OrgName = "North",
  AcctCode = "FTW"
};

User user2 = new User()
{
  Name = "Test User",
  IdNumber = "1000354",
  OrgName = "North",
  AcctCode = "FTW"
};

var doesEqual = user1.Equals(user2);
Console.WriteLine(doesEqual); // Returns FALSE

I also have TWO lists that have same objects in them, except for one.

When I do the Except, it doesn't want to work right and returns 131.

List<User> ListOne; // Contains 131 User objects
List<User> ListTwo; // Contains 130 User objects
var difference = ListOne.Except(ListTwo);
Console.WriteLine(difference); // Returns 131

What am I doing wrong??

huysentruitw
  • 27,376
  • 9
  • 90
  • 133
Turp
  • 708
  • 3
  • 14
  • 26

6 Answers6

2

By default, reference types will compare references. Meaning that your 2 separate instances, even though their fields have the same value, are different object and will compare as inequal. You can change this behavior by having your class implement IEquatable<T> to "teach" it how to compare any way you want.

A great example, that almost matches your usage, can be found on MSDN.

Bradley Uffner
  • 16,641
  • 3
  • 39
  • 76
1

Class default equality criteria is by reference. It should return false.

You can override Equals method (and then you will have to implement GetHashCode) to whatever logic you want.

public override bool Equals(object obj)
{    

    if(!(obj is User)) 
    {
        return false;
    }

     User user= obj as User;
    return user.Name == Name && user.IdNumber == IdNumber && user.OrgName == OrgName && user.AcctCode == AcctCode;
}

public override int GetHashCode()
{
    return IdNumber.GetHashCode();
}
huysentruitw
  • 27,376
  • 9
  • 90
  • 133
Yosi Dahari
  • 6,794
  • 5
  • 24
  • 44
0

Despite the fact that all the properties of your objects have the same value, they are two completely different object. This user1 holds a reference to the heap for an object with some values. The same holds for user2. That being said this are two different references to the heap.

If you don't override the Equals method, then the equality is based on the references. So the objects are different, even when they have exactly the same values for all of their properties.

Christos
  • 53,228
  • 8
  • 76
  • 108
0

They are not equal because User is a class (i.e. a "reference type"). For reference types, .Equals compares reference equality, and the two instances user1 and user2 are two separate references.

rory.ap
  • 34,009
  • 10
  • 83
  • 174
  • See this [MSDN article](https://msdn.microsoft.com/en-us/library/bsc2ak47(v=vs.110).aspx) about the `Object.Equals` method. When comparing value types `int`, `bool`, `long`, et cetera, `Object.Equals` will perform as you expect. – BenM Dec 17 '15 at 18:05
  • @BenM -- Thanks, but that's irrelevant. The OP is comparing reference types, not value types. – rory.ap Dec 17 '15 at 18:39
0

The problem is this line:

user1.Equals(user2)

This line is asking if the user1 object the same as the user2 object. They have the same values but they are not the same object in memory. If you want to compare the values of these two objects you can override the Equals method like so:

public static override Equals(User user2)
{
    return (this.Name == user2.Name &&
            this.IdNumber == user2.IdNumber &&
            this.AcctCode == user2.AcctCode &&
            this.OrgName == user2.OrgName) 
}
wentimo
  • 471
  • 3
  • 12
  • 2
    Be careful with this approach -- it's very brittle as any future updater of the class will have to remember to modify this method to accommodate any changes. – rory.ap Dec 17 '15 at 18:07
  • 1
    make sure you do it right: "It is recommended that any class that overrides Equals also override System.Object.GetHashCode." [Guidelines for Overloading Equals()](https://msdn.microsoft.com/en-US/library/ms173147(v=vs.80).aspx) – Victor Bouhnik Dec 17 '15 at 18:11
-1

Your class User does not implement anything to tell the runtime when two objects are equal. The simpliest way to acchieve this is by overwriting the two Methods Equals and GetHashCode like this:

public override bool Equals(object obj)
{    
    User other = obj as User;
    if( other == null ) return false;
    return other.Name == Name && other.IdNumber == IdNumber && other.OrgName == OrgName && other.AcctCode == AcctCode;
}

public override int GetHashCode()
{
    return IdNumber.GetHashCode();
}
CSharpie
  • 9,195
  • 4
  • 44
  • 71