概述
LINQ中的SequenceEqual
操作符用于检查两个集合(序列)是否相等。如果两个序列相等,则返回true
,否则返回false
。
注意,这里所说的相等包括:集合中元素的数量、每个元素的值和元素的顺序是否相等。
如果集合包含基本数据类型的元素,则比较元素的值和数量,而包含复杂类型元素的集合则检查对象的引用。所以,如果两个对象有相同的引用,那么它们被认为是相等的,否则它们被认为是不相等的。
SequenceEqual
包含如下两个重载:
public static bool SequenceEqual<TSource>(this IEnumerable<TSource> first, IEnumerable<TSource> second)
public static bool SequenceEqual<TSource>(this IEnumerable<TSource> first, IEnumerable<TSource> second, IEqualityComparer<TSource>? comparer)
以下是使用SequenceEqual
对两个基本数据类型(int
)集合进行的相等性比较:
using System;
using System.Collections.Generic;
using System.Linq;
namespace LinqTutorial
{
public class MyProgram
{
static void Main(string[] args)
{
var numbers1 = new List<int> { 1, 2, 3, 4, 5 };
var numbers2 = new List<int> { 1, 2, 3, 4, 5 };
var isEqual = numbers1.SequenceEqual(numbers2);
Console.WriteLine($"集合1与集合2是否相同:{isEqual}");
Console.Read();
}
}
}
运行结果:
集合1与集合2是否相同:True
由于集合numbers1
与numbers2
中元素的数量、每个元素的值和元素的顺序均相同,所以这两个集合是相等的。
现在,我们将集合numbers2
中的数字2
和3
的位置互换,之后再调用SequenceEqual
方法,示例如下:
using System;
using System.Collections.Generic;
using System.Linq;
namespace LinqTutorial
{
public class MyProgram
{
static void Main(string[] args)
{
var numbers1 = new List<int> { 1, 2, 3, 4, 5 };
var numbers2 = new List<int> { 1, 3, 2, 4, 5 };
var isEqual = numbers1.SequenceEqual(numbers2);
Console.WriteLine($"集合1与集合2是否相同:{isEqual}");
Console.Read();
}
}
}
运行结果:
集合1与集合2是否相同:False
复杂类型的SequenceEqual操作
假如有如下的Customer.cs
类,此类中分别有GetCustomers1()
和GetCustomers2()
方法来获取2个不同Customer
集合实例,集合中的Customer
数据相同。现使用SequenceEqual()
方法比较这两个集合是否相同:
namespace LinqTutorial
{
public class Program
{
static void Main(string[] args)
{
var customers1 = Customer.GetCustomers1();
var customers2 = Customer.GetCustomers2();
var isEquals = customers1.SequenceEqual(customers2);
Console.WriteLine($"Customer1集合是否与Customer2集合相等:{isEquals}");
Console.ReadKey();
}
}
public class Customer
{
public int Id { get; set; }
public string? Name { get; set; }
public static List<Customer> GetCustomers1()
{
var listCustomers = new List<Customer>()
{
new() {Id= 101,Name = "Rector"},
new() {Id= 102,Name = "Curry"}
};
return listCustomers;
}
public static List<Customer> GetCustomers2()
{
var listCustomers = new List<Customer>()
{
new() {Id= 101,Name = "Rector"},
new() {Id= 102,Name = "Curry"}
};
return listCustomers;
}
}
}
运行结果:
Customer1集合是否与Customer2集合相等:False
从运行的结果可以看到,虽然Customer1和Customer2集合的数据相同,但它们是不同的实例,所以SequenceEqual()
方法比较出来的结果为False
。
为了使用SequenceEqual()
方法比较两个复杂类型的值是否相同,则要实现IEqualityComparer<T>
的泛型接口,如下的CustomerComparer
类:
public class CustomerComparer : IEqualityComparer<Customer>
{
public bool Equals(Customer x, Customer y)
{
if (x.Id == y.Id && x.Name == y.Name)
{
return true;
}
return false;
}
public int GetHashCode(Customer obj)
{
return obj.Id.GetHashCode();
}
}
使用示例:
namespace LinqTutorial
{
public class Program
{
static void Main(string[] args)
{
var customers1 = Customer.GetCustomers1();
var customers2 = Customer.GetCustomers2();
var isEquals = customers1.SequenceEqual(customers2, new CustomerComparer());
Console.WriteLine($"Customer1集合是否与Customer2集合相等:{isEquals}");
Console.ReadKey();
}
}
public class Customer
{
public int Id { get; set; }
public string? Name { get; set; }
public static List<Customer> GetCustomers1()
{
var listCustomers = new List<Customer>()
{
new() {Id= 101,Name = "Rector"},
new() {Id= 102,Name = "Curry"}
};
return listCustomers;
}
public static List<Customer> GetCustomers2()
{
var listCustomers = new List<Customer>()
{
new() {Id= 101,Name = "Rector"},
new() {Id= 102,Name = "Curry"}
};
return listCustomers;
}
}
public class CustomerComparer : IEqualityComparer<Customer>
{
public bool Equals(Customer x, Customer y)
{
if (x.Id == y.Id && x.Name == y.Name)
{
return true;
}
return false;
}
public int GetHashCode(Customer obj)
{
return obj.Id.GetHashCode();
}
}
}
请注意如下语句:
var isEquals = customers1.SequenceEqual(customers2, new CustomerComparer());
此语句中,调用了SequenceEqaul()
方法的2个参数的重载方法,传入了实现IEqualityComparer<T>
的实现类CustomerComparer
的实例作为第2个参数。
运行结果:
Customer1集合是否与Customer2集合相等:True
重写Equals方法
对于比较两个复杂类型的SequenceEqual()
,除了实现IEqualityComparer<T>
接口外,还可以重写Equals()
方法来实现,比如我们重写本例Customer
类的Equals()
方法,示例如下:
namespace LinqTutorial
{
public class Program
{
static void Main(string[] args)
{
var customers1 = Customer.GetCustomers1();
var customers2 = Customer.GetCustomers2();
var isEquals = customers1.SequenceEqual(customers2);
Console.WriteLine($"Customer1集合是否与Customer2集合相等:{isEquals}");
Console.ReadKey();
}
}
public class Customer
{
public int Id { get; set; }
public string? Name { get; set; }
public static List<Customer> GetCustomers1()
{
var listCustomers = new List<Customer>()
{
new() {Id= 101,Name = "Rector"},
new() {Id= 102,Name = "Curry"}
};
return listCustomers;
}
public static List<Customer> GetCustomers2()
{
var listCustomers = new List<Customer>()
{
new() {Id= 101,Name = "Rector"},
new() {Id= 102,Name = "Curry"}
};
return listCustomers;
}
public override bool Equals(object? obj)
{
if (obj == null)
{
return false;
}
if (((Customer)obj).Id == Id && ((Customer)obj).Name == Name)
{
return true;
}
return false;
}
}
}
运行结果:
Customer1集合是否与Customer2集合相等:True
发表评论
登录用户才能发表评论, 请 登 录 或者 注册