views:

126

answers:

2

Consider these two structures:

struct Task
{
    public Int32 Id;
    public String Name;
    public List<Registration> Registrations;
}

struct Registration
{
    public Int32 Id;
    public Int32 TaskId;
    public String Comment;
    public Double Hours;
}

I am selecting a bunch of entries in a DataTable into new structures, like so:

var tasks = data.AsEnumerable().Select(t => new Task
{
    Id = Convert.ToInt32(t["ProjectTaskId"]),
    Name = Convert.ToString(t["ProjectTaskName"]),
    Registrations = new List<Registration>()
});

But when I call Distinct() on the collection, it doesn't recognize objects with the same values (Id, Name, Registrations) as being equal.

But if I use an equality comparer; comparing the Id property on the objects, it's all fine and dandy...:

class TaskIdComparer : IEqualityComparer<Task>
{
    public bool Equals(Task x, Task y)
    {
        return x.Id == y.Id;
    }


    public Int32 GetHashCode(Task t)
    {
        return t.Id.GetHashCode();
    }
}

What am I missing here? Is Distinct() checking something else than the value of properties?

+3  A: 

LINQ's Distinct method compares objects using the objects' Equals and GetHashCode implementations.
Therefore, if these methods are not overridden, it will compare by reference, not by value.

You need to use an EqualityComparer. (Or implement Equals and GetHashCode for the Task class)

SLaks
...which, undoubtedly, fails for the list of registrations.
tvanfosson
tvan, from the code only the Id is significant.
Henk Holterman
And the reference, in this case, would be what?
roosteronacid
@roosteronacid: By default, it will only consider two references equal if they refer to the same instance.
SLaks
Thanks SLaks. That really boggled my head :)
roosteronacid
My thousandth answer!
SLaks
A: 

my guess is that it's the list in there. Almost certainly, the two list objects are different, even if they contain the same info.

Steve Cooper