C#List使用Linq去重

     发布时间:2021-12-22 13:41:18

C#使用Linq的Distinct函数去除List中的重复元素

使用Linq的Distinct函数去除List中的重复元素

不过这个去重对象依赖List中的元素实现Equals方法和GetHashCode方法。

var list = new List<int>() {1, 1, 2, 2, 1, 3};
var newList = list.Distinct().ToList();
Console.WriteLine(string.Join(",", newList));//输出结果:1,2,3

如果是自定义的引用类型不自己实现Equals方法和GetHashCode方法,则会导致无法去重(因为引用类型都继承自Object,他默认提供的Equals方法和GetHashCode方法是基于引用来判断的)
如果是自定义的结构类型不自己实现Equals方法和GetHashCode方法,虽然可以去重但是性能低下(因为结构类型都继承自ValueType,他默认会用反射实现Equals方法和GetHashCode方法)

自定义对象未实现Equals方法和GetHashCode方法

static void Main(string[] args)
{
    var list = new List<Person>()
    {
        new Person {Id = 1, Name = "张三"},
        new Person {Id = 1, Name = "张三"},
        new Person {Id = 2, Name = "李四"},
        new Person {Id = 3, Name = "王五"},
    };
    var newList = list.Distinct().ToList();
    Console.WriteLine(string.Join("\r\n", newList));
}

public class Person
{
    public int Id { get; set; }
    public string Name { get; set; }

    public override string ToString()
    {
        return $"{Id},{Name}";
    }
}

输出结果:

1,张三
1,张三
2,李四
3,王五

自定义对象实现Equals方法和GetHashCode方法

如果是自定义的值类型建议也实现IEquatable<>接口,可以避免去重的时候反复拆装箱产生性能问题!

static void Main(string[] args)
{
    var list = new List<Person>()
    {
        new Person {Id = 1, Name = "张三"},
        new Person {Id = 1, Name = "张三"},
        new Person {Id = 2, Name = "李四"},
        new Person {Id = 3, Name = "王五"},
    };
    var newList = list.Distinct().ToList();
    Console.WriteLine(string.Join("\r\n", newList));
}

public class Person : IEquatable<Person>
{
    public int Id { get; set; }
    public string Name { get; set; }

    public override string ToString()
    {
        return $"{Id},{Name}";
    }

    public bool Equals(Person other)
    {
        if (ReferenceEquals(null, other)) return false;
        if (ReferenceEquals(this, other)) return true;
        return Id == other.Id && Name == other.Name;
    }

    public override bool Equals(object obj)
    {
        if (ReferenceEquals(null, obj)) return false;
        if (ReferenceEquals(this, obj)) return true;
        if (obj.GetType() != this.GetType()) return false;
        return Equals((Person) obj);
    }

    public override int GetHashCode()
    {
        unchecked
        {
            return (Id * 397) ^ (Name != null ? Name.GetHashCode() : 0);
        }
    }
}

输出结果:

1,张三
2,李四
3,王五