怎么使用LINQ方法来比较自定义类型对象

 LINQ提供了方便的语法和很多操作对象集合的有用的方法。但是,要让LINQ比较方法,如Distinct或Intersect能正确处理,类型必须要满足一些条件。让我们看看Distinct方法,它从集合中返回所有的不重复对象。

 

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

var distinctNumbers = numbers.Distinct();

foreach (var number in distinctNumbers)

    Console.WriteLine(number);

 

输出: 1 2 3

 

但是如果你想在你自定义类型对象的集合使用Distinct方法呢?例如,像这样:

 

class Number

{

    public int Digital { get; set; }

    public String Textual { get; set; }

}

 

class Program

{

    static void Main(string[] args)

    {

       List<Number> numbers = new List<Number> {

           new Number { Digital = 1, Textual = "one" },

           new Number { Digital = 1, Textual = "one" } ,

           new Number { Digital = 2, Textual = "two" } ,

           new Number { Digital = 3, Textual = "three" } ,

           };

 

       var distinctNumbers = numbers.Distinct();

 

       foreach (var number in distinctNumbers)

                   Console.WriteLine(number.Digital);

    }

}

 

 

代码可以通过编译,但输出却不一样:1 1 2 3

 

为什么会这样?答案在LINQ的实现细节里。要让Distinct方法正确处理,类型必须重写object的Equals和GetHashCode方法便可,并必须实现IEquatable<T>

 

那么,上个例子的Number类实际上需要看起来像这样:

 

 

class Number: IEquatable<Number>

{

    public int Digital { get; set; }

    public String Textual { get; set; }

 

    public bool Equals(Number other)

    {

 

        // 检查被比较的对象是否为null。

        if (Object.ReferenceEquals(other, null)) return false;

 

        // 检查是否引用的相同对象。

        if (Object.ReferenceEquals(this, other)) return true;

 

        // 检查对象的属性是否相等。

 

        return Digital.Equals(other.Digital) &&

 

               Textual.Equals(other.Textual);

    }

 

    // 如果比较两个对象是相等的,

    // 那么这两个对象的GetHashCode方法必须返回一样的值。

 

    public override int GetHashCode()

    {

        // 如果Textual字段不为空,则获取它的哈希值。

        int hashTextual = Textual == null ? 0 : Textual.GetHashCode();

 

        // 获取Digital字段的哈希值

        int hashDigital = Digital.GetHashCode();

 

        // 计算对象的哈希值。

        return hashDigital ^ hashTextual;

    }

}

 

但假如你无法改变此类型呢?如果它在一个库里而你没有办法让此类型实现IEquatable<T>接口呢?答案是创建一个你自己的比较器然后将其通过参数传递给Distinct方法。

 

相等比较器必须实现IEqualityComparer<T>接口,且同样提供GetHashCode和Equals方法。

 

这里是怎么为原Number类实现相等比较器,大概像这样:

 

class NumberComparer : IEqualityComparer<Number>

{

    public bool Equals(Number x, Number y)

    {

        if (Object.ReferenceEquals(x, y)) return true;

 

        if (Object.ReferenceEquals(x, null) ||

            Object.ReferenceEquals(y, null))

                return false;

 

            return x.Digital == y.Digital && x.Textual == y.Textual;

    }

 

    public int GetHashCode(Number number)

    {

        if (Object.ReferenceEquals(number, null)) return 0;

 

        int hashTextual = number.Textual == null

            ? 0 : number.Textual.GetHashCode();

 

        int hashDigital = number.Digital.GetHashCode();

 

        return hashTextual ^ hashDigital;

    }

}

 

不要忘记将比较器传递给Distinct方法:

 

var distinctNumbers = numbers.Distinct(new NumberComparer());

 

当然,这个规则不仅仅适用于Distinct方法。例如,同样可以用于Contains,Except,Intersect,和Union方法。通常,如果你看到此LINQ方法有个接受IEqualityComparer<T>参数的重载,这可能表示对你自己的类型使用此方法时,你需要在你的类中实现IEquatable<T>接口或创建你自己的相等比较器

 

转载于:https://www.cnblogs.com/supperwu/archive/2010/03/06/LINQ.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
智慧校园的建设目标是通过数据整合、全面共享,实现校园内教学、科研、管理、服务流程的数字化、信息化、智能化和多媒体化,以提高资源利用率和管理效率,确保校园安全。 智慧校园的建设思路包括构建统一支撑平台、建立完善管理体系、大数据辅助决策和建设校园智慧环境。通过云架构的数据中心与智慧的学习、办公环境,实现日常教学活动、资源建设情况、学业水平情况的全面统计和分析,为决策提供辅助。此外,智慧校园还涵盖了多媒体教学、智慧录播、电子图书馆、VR教室等多种教学模式,以及校园网络、智慧班牌、校园广播等教务管理功能,旨在提升教学品质和管理水平。 智慧校园的详细方案设计进一步细化了教学、教务、安防和运维等多个方面的应用。例如,在智慧教学领域,通过多媒体教学、智慧录播、电子图书馆等技术,实现教学资源的共享和教学模式的创新。在智慧教务方面,校园网络、考场监控、智慧班牌等系统为校园管理提供了便捷和高效。智慧安防系统包括视频监控、一键报警、阳光厨房等,确保校园安全。智慧运维则通过综合管理平台、设备管理、能效管理和资产管理,实现校园设施的智能化管理。 智慧校园的优势和价值体现在个性化互动的智慧教学、协同高效的校园管理、无处不在的校园学习、全面感知的校园环境和轻松便捷的校园生活等方面。通过智慧校园的建设,可以促进教育资源的均衡化,提高教育质量和管理效率,同时保障校园安全和提升师生的学习体验。 总之,智慧校园解决方案通过整合现代信息技术,如云计算、大数据、物联网和人工智能,为教育行业带来了革命性的变革。它不仅提高了教育的质量和效率,还为师生创造了一个更加安全、便捷和富有智慧的学习与生活环境。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值