首页 / 教程列表 / LINQ教程 / LINQ操作符之SequenceEqual

LINQ操作符之SequenceEqual

733 更新于: 2023-01-16 读完约需 20 分钟

概述

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

由于集合numbers1numbers2中元素的数量、每个元素的值和元素的顺序均相同,所以这两个集合是相等的。

现在,我们将集合numbers2中的数字23的位置互换,之后再调用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

版权声明:本作品系原创,版权归码友网所有,如未经许可,禁止任何形式转载,违者必究。

本文永久链接码友网 » LINQ教程 » LINQ操作符之SequenceEqual 分享:

发表评论

登录用户才能发表评论, 请 登 录 或者 注册