Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Create List<CustomObject> from List<OtherObject>, removing duplicates.

Tags:

c#

linq

There's a very related question: Create List<CustomObject> from List<string> however it doesn't deal with removing duplicates at the same time.

I have the following class examples:

class Widget
{
    public string OwnerName;
    public int SomeValue;
}

class Owner
{
    public string Name;
    public string OtherData;
}

I'd like to create a list of owners based on a list of Widgets, but only unique owner names.

Here is what I tried:

List<Owner> Owners = MyWidgetList.Select(w => new Owner { Name = w.OwnerName }).Distinct().ToList();

The problem is that there are repeats in the resulting list. What am I doing wrong?

like image 277
JYelton Avatar asked Feb 05 '26 06:02

JYelton


1 Answers

You need to define GetHashCode() and Equals() for your object to define what equality is for your custom type. Otherwise it compares based on the reference itself.

This is because the LINQ extension methods use the IEqualityComparer interface to compare objects. If you don't define a custom comparer (which you can do by creating a separate class that implements IEqualityComparer<Owner>) it will use the default equality comparer, which uses the class's Equals() and GetHashCode() definition. Which, if you don't override them, does reference comparisons on Equals() and returns the default object hash code.

Either define a custom IEqualityComparer<Owner> (since you're calling distinct on a sequence of Owner) or add a Equals() and GetHashCode() for your class.

public class Owner
{
    public string Name;
    public string OtherData;

    public override Equals(object other)
    {
        if (ReferenceEquals(this, other))
            return true;

        if (other == null)
            return false;

        // whatever your definition of equality is...
        return Name == other.Name && OtherData == other.OtherData;
    }

    public override int GetHashCode()
    {
        int hashCode = 0;

        unchecked
        {
           // whatever hash code computation you want, but for example...
            hashCode += 13 * Name != null ? Name.GetHashCode() : 0;
            hashCode += 13 * OtherData != null ? OtherData.GetHashCode() : 0;
        }

        return hashCode;
    }
}

Once you do that, the query you have written will work just fine.

like image 148
James Michael Hare Avatar answered Feb 07 '26 01:02

James Michael Hare