Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/274.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何从列表中删除重复项<;T>;?_C#_List - Fatal编程技术网

C# 如何从列表中删除重复项<;T>;?

C# 如何从列表中删除重复项<;T>;?,c#,list,C#,List,我正在关注一个关于在C#中从列表中删除重复项的stackoverflow 如果是某个用户定义的类型,如: class Contact { public string firstname; public string lastname; public string phonenum; } 建议的(HashMap)不会删除重复项。我想,我必须重新定义一些比较两个对象的方法,不是吗?AHashSet确实会删除重复项,因为它是一个集合。。。但只有当您的类型正确定义相等时 我怀疑

我正在关注一个关于在C#中从
列表中删除重复项的stackoverflow

如果
是某个用户定义的类型,如:

class Contact
{
    public string firstname;
    public string lastname;
    public string phonenum;
}
建议的(HashMap)不会删除重复项。我想,我必须重新定义一些比较两个对象的方法,不是吗?

A
HashSet
确实会删除重复项,因为它是一个集合。。。但只有当您的类型正确定义相等时

我怀疑“复制”是指“与另一个对象具有相同字段值的对象”-您需要覆盖
Equals
/
GetHashCode
,以使其工作,和/或实现。。。或者您可以向
HashSet
构造函数提供
IEqualityComparer

您可以调用
Distinct
LINQ扩展方法,而不是使用
HashSet
。例如:

list = list.Distinct().ToList();
但是,无论如何,你需要提供一个适当的平等定义

下面是一个示例实现。请注意我是如何使其不可变的(对于可变类型,相等是奇怪的,因为两个对象可以在一分钟内相等,下一分钟则不相等)和 …制造的 字段是私有的,具有公共属性。最后,我已经密封了类-不可变类型通常应该密封,这使得平等更容易讨论

using System;
using System.Collections.Generic; 

public sealed class Contact : IEquatable<Contact>
{
    private readonly string firstName;
    public string FirstName { get { return firstName; } }

    private readonly string lastName;
    public string LastName { get { return lastName; } }

    private readonly string phoneNumber;
    public string PhoneNumber { get { return phoneNumber; } }

    public Contact(string firstName, string lastName, string phoneNumber)
    {
        this.firstName = firstName;
        this.lastName = lastName;
        this.phoneNumber = phoneNumber;
    }

    public override bool Equals(object other)
    {
        return Equals(other as Contact);
    }

    public bool Equals(Contact other)
    {
        if (object.ReferenceEquals(other, null))
        {
            return false;
        }
        if (object.ReferenceEquals(other, this))
        {
            return true;
        }
        return FirstName == other.FirstName &&
               LastName == other.LastName &&
               PhoneNumber == other.PhoneNumber;
    }

    public override int GetHashCode()
    {
        // Note: *not* StringComparer; EqualityComparer<T>
        // copes with null; StringComparer doesn't.
        var comparer = EqualityComparer<string>.Default;

        // Unchecked to allow overflow, which is fine
        unchecked
        {
            int hash = 17;
            hash = hash * 31 + comparer.GetHashCode(FirstName);
            hash = hash * 31 + comparer.GetHashCode(LastName);
            hash = hash * 31 + comparer.GetHashCode(PhoneNumber);
            return hash;
        }
    }
}


对于这个任务,我不一定认为实现IComparable是显而易见的解决方案。您可能希望以多种不同的方式对唯一性进行排序和测试

我倾向于实现一个
IEqualityComparer


注:说到
HashSet
请注意
HashSet
IEqualityComparer
作为构造函数参数。

这正是我所写的(如果不是太晚的话:-)GetHashCode()的实现需要附带解释性注释。我的大脑不在你的水平上运行。你能用GetHashCode方法吗?我似乎不这么认为。@Sandy,@Chris:在底部添加了一个关于哈希代码的编辑。抱歉花了这么长时间。
public override int GetHashCode()
{
    // Unchecked to allow overflow, which is fine
    unchecked
    {
        int hash = 17;
        hash = hash * 31 + (FirstName ?? "").GetHashCode();
        hash = hash * 31 + (LastName ?? "").GetHashCode();
        hash = hash * 31 + (PhoneNumber ?? "").GetHashCode();
        return hash;
    }
}
public override int GetHashCode()
{
    // Unchecked to allow overflow, which is fine
    unchecked
    {
        int hash = 17;
        hash = hash * 31 + (FirstName == null ? 0 : FirstName.GetHashCode());
        hash = hash * 31 + (LastName == null ? 0 : LastName.GetHashCode());
        hash = hash * 31 + (PhoneNumber == null ? 0 : PhoneNumber.GetHashCode());
        return hash;
    }
}
class Contact {
    public int Id { get; set; }
    public string Name { get; set; }

    public override string ToString()
    {
        return string.Format("{0}:{1}", Id, Name);
    }

    static private IEqualityComparer<Contact> comparer;
    static public IEqualityComparer<Contact> Comparer {
        get { return comparer ?? (comparer = new EqualityComparer()); }
    }

    class EqualityComparer : IEqualityComparer<Contact> {
        bool IEqualityComparer<Contact>.Equals(Contact x, Contact y)
        {
            if (x == y) 
                return true;

            if (x == null || y == null)
                return false;

            return x.Name == y.Name; // let's compare by Name
        }

        int IEqualityComparer<Contact>.GetHashCode(Contact c)
        {
            return c.Name.GetHashCode(); // let's compare by Name
        }
    }
}

class Program {
    public static void Main()
    {
        var list = new List<Contact> {
            new Contact { Id = 1, Name = "John" },
            new Contact { Id = 2, Name = "Sylvia" },
            new Contact { Id = 3, Name = "John" }
        };

        var distinctNames = list.Distinct(Contact.Comparer).ToList();
        foreach (var contact in distinctNames)
            Console.WriteLine(contact);
    }
}
1:John
2:Sylvia
sealed class ContactFirstNameLastNameComparer : IEqualityComparer<Contact>
{
  public bool Equals (Contact x, Contact y)
  {
     return x.firstname == y.firstname && x.lastname == y.lastname;
  }

  public int GetHashCode (Contact obj)
  {
     return obj.firstname.GetHashCode () ^ obj.lastname.GetHashCode ();
  }
}
var unique = contacts.Distinct (new ContactFirstNameLastNameComparer ()).ToArray ();