从List <OtherObject>创建List <CustomObject>,删除重复项.

JYe*_*ton 3 c# linq

有一个非常相关的问题:从List <string>创建List <CustomObject>但是它不处理同时删除重复项.

我有以下类示例:

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

class Owner
{
    public string Name;
    public string OtherData;
}
Run Code Online (Sandbox Code Playgroud)

我想根据小部件列表创建一个所有者列表,但只有唯一的所有者名称.

这是我尝试过的:

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

问题是结果列表中有重复.我究竟做错了什么?

Jam*_*are 5

您需要定义GetHashCode()Equals()为您的对象定义自定义类型的相等性.否则,它会根据引用本身进行比较.

这是因为LINQ扩展方法使用IEqualityComparer接口来比较对象.如果没有定义自定义比较器(可以通过创建一个单独的类来实现IEqualityComparer<Owner>),它将使用默认的相等比较器,它使用类Equals()GetHashCode()定义.其中,如果不覆盖它们,则引用比较Equals()并返回默认对象哈希码.

无论是定义一个定制IEqualityComparer<Owner>(因为你调用者的顺序不同)或添加Equals(),并GetHashCode()为你的类.

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;
    }
}
Run Code Online (Sandbox Code Playgroud)

一旦你这样做,你写的查询将正常工作.


dle*_*lev 5

默认比较器Owner无法正常工作(因为它只是使用引用相等)所以Distinct认为所有对象都是不同的.一种解决方案是使用两个Selects:

var owners = MyWidgetList.Select(w => w.OwnerName).Distinct().Select(w => new Owner { Name = w }).ToList();
Run Code Online (Sandbox Code Playgroud)

或者,您可以实现EqualsGetHashCode启用Owner,并且您的原始方法将起作用.