先来看看泛型链表 List<T> 的定义:
public class List<T> : IList<T>, ICollection<T>, IList, ICollection, IReadOnlyList<T>, IReadOnlyCollection<T>, IEnumerable<T>, IEnumerable
可见它实现了 IEnumerable<T>,而IEnumerable<T>规定了Distinct方法。
使用这个方法时要注意:
(1)该方法并不会改变原来的链表;
(2)该方法返回一个对象(假设叫做dis),通过该对象可以枚举原链表中的非重复元素,但是并没有把非重复元素复制一份到新的对象中(连签拷贝也没有)
(3)由于(2),在枚举dis时,始终是依赖于原有链表,所以如果在获得dis后,又更新了原有链表,那么使用dis枚举将会使用原有链表的最新状态。
using System; using System.Collections.Generic; using System.Linq; namespace ConsoleApplication2 { class IntroToLINQ { static void Main() { List<A> list = new List<A>(); A a = new A(100); list.Add(a); list.Add(a); list.Add(a); IEnumerable<A> distinct = list.Distinct(); //对distinct进行第一次枚举 Console.WriteLine("第一次枚举"); foreach (A aa in distinct) { Console.WriteLine(aa.X); } //改变原有链表 list.Add(new A(200)); //在此对distinct进行枚举 Console.WriteLine("第二次枚举"); foreach (A aa in distinct) { Console.WriteLine(aa.X); } } } class A { private int x; public A(int x) { this.x = x; } public int X { get { return x; } } } }
输出结果:
第一次枚举
100
第二次枚举
100
200
Press any key to continue . . .
List<T>的Distinct()方法返回的是一个看待原有链表的视角,类似于Sql语句,其本身并没有存放任何元素,其枚举始终依赖于原有链表。如果要得到一个原有链表的真正非重复元素集合,可以参考如下代码:
using System; using System.Collections.Generic; using System.Linq; namespace ConsoleApplication2 { class IntroToLINQ { static void Main() { List<A> list = new List<A>(); A a = new A(100); list.Add(a); list.Add(a); list.Add(a); IEnumerable<A> distinct = list.Distinct(); //获得list的非重复元素组成的新链表list2 List<A> list2 = new List<A>(); foreach (A aa in distinct) { list2.Add(aa); } list = list2; //如果原有链表不要了,可以重新赋值 } } class A { private int x; public A(int x) { this.x = x; } public int X { get { return x; } } } }