c# Linq distinct不会调用Equals方法详解

1. Linq中的Distinct方法

Linq(Language Integrated Query)是使用C#编程语言进行查询的统一查询语言。它提供了一种简洁的语法来执行各种查询操作,如过滤、排序、投影等。Linq提供了一个Distinct方法,用于从数据集合中去除重复的元素。

2. Distinct方法的用法

Distinct方法可以应用于各种Linq查询表达式,包括从List、Array、集合、数据库等数据源中查询。它返回一个新的序列,其中包含原始序列中具有不同值的元素。

Distinct方法没有重载,它默认根据元素的Equals方法进行比较来判断是否为重复元素。例如:

var numbers = new List<int> { 1, 2, 2, 3, 3, 4, 5 };

var distinctNumbers = numbers.Distinct();

上述代码中,numbers列表中有重复的元素2和3,使用Distinct方法会生成一个不包含重复元素的新列表distinctNumbers。结果为1, 2, 3, 4, 5。

3. Equals方法在Distinct中的作用

根据标题所提到的问题,Linq的Distinct方法不会调用元素的Equals方法,这是因为默认情况下Linq使用引用类型的默认比较器进行元素比较,而不是调用元素的Equals方法。因此,即使我们在元素类中重写了Equals方法,Distinct方法仍然不会使用它来判断是否为重复元素。

3.1 示例

以一个自定义类Person为例,Person类有一个属性Name:

class Person

{

public string Name { get; set; }

public override bool Equals(object obj)

{

if (obj == null || GetType() != obj.GetType())

{

return false;

}

return Name == ((Person)obj).Name;

}

public override int GetHashCode()

{

return Name.GetHashCode();

}

}

我们创建一个Person对象列表people:

var people = new List<Person>

{

new Person{Name = "Alice"},

new Person{Name = "Bob"},

new Person{Name = "Alice"}

};

如果我们调用people的Distinct方法:

var distinctPeople = people.Distinct();

结果是不会去除重复的Person对象,而是返回原始列表people。

4. 如何实现自定义的比较逻辑

如果我们想使用自定义的比较逻辑来判断元素是否为重复元素,有几种方法可以实现:

4.1 IEqualityComparer接口

我们可以实现IEqualityComparer接口,然后将实现的比较器作为参数传递给Distinct方法。以下是一个使用IEqualityComparer的示例:

class PersonComparer : IEqualityComparer<Person>

{

public bool Equals(Person x, Person y)

{

return x.Name == y.Name;

}

public int GetHashCode(Person obj)

{

return obj.Name.GetHashCode();

}

}

var distinctPeople = people.Distinct(new PersonComparer());

上述代码中,我们创建一个名为PersonComparer的类,实现了IEqualityComparer<Person>接口的Equals和GetHashCode方法。在调用Distinct方法时,将PersonComparer的实例作为参数传递给Distinct方法。

此时,Distinct方法将会使用PersonComparer的Equals方法来判断元素是否为重复元素。调用结果将是去除了重复元素的Person列表。

4.2 延迟加载查询

另一种方法是使用延迟加载查询,先筛选出不重复的元素,再使用ToList方法将查询结果转换为List。以下是一个示例:

var distinctPeople = people.Where((p, index) => people.FindLastIndex(person => person.Name == p.Name) == index).ToList();

上述代码中,我们使用Where方法和FindLastIndex方法来筛选出不重复的元素。FindLastIndex方法返回匹配元素的最后一个索引,我们可以检查是否和当前索引相等来判断是否为重复元素。最后使用ToList方法将查询结果转换为List。

这种方法的缺点是代码复杂且不易理解,只适用于小数据集的情况,对于大数据集的性能会有明显的影响。

5. 总结

Linq的Distinct方法提供了一种方便的方式来去除序列中的重复元素。但默认情况下,Distinct方法使用引用类型的默认比较器进行元素比较,而不是调用元素的Equals方法。

如果我们希望使用自定义的比较逻辑来判断元素是否为重复元素,可以实现IEqualityComparer接口并将比较器作为参数传递给Distinct方法。另一种方法是使用延迟加载查询,先筛选出不重复的元素,再将结果转换为List。

希望本文对理解Linq的Distinct方法以及解决常见问题有所帮助。

免责声明:本文来自互联网,本站所有信息(包括但不限于文字、视频、音频、数据及图表),不保证该信息的准确性、真实性、完整性、有效性、及时性、原创性等,版权归属于原作者,如无意侵犯媒体或个人知识产权,请来电或致函告之,本站将在第一时间处理。猿码集站发布此文目的在于促进信息交流,此文观点与本站立场无关,不承担任何责任。

后端开发标签