Microsoft.NET 框架程序设计 —— 通用对象操作

本文深入探讨了.NET框架中对象的等值性与唯一性,介绍了如何为不同类型(包括引用类型和值类型)实现Equals方法,并遵循自反性、对称性、传递性和一致性原则。同时,讲解了如何判断对象的唯一性,以及对象的散列码在散列表中的作用。最后,讨论了对象克隆的概念,包括浅拷贝和深拷贝,并展示了如何实现ICloneable接口。
摘要由CSDN通过智能技术生成

对象的等值性与惟一性

        如前所述,System.Obiect类型提供了一个名为Equals 的虚方法,其目的为判断两个对象是否有着相同的“值”。微软的.NET框架类库(FCL)中包括的许多方法(例如 System.Array的IndexOf方法System.Collections.ArrayList的 Contains 方法)在内部都调用到了 Equals方法。因为 Equals 方法定义在Obiect中,而每个类型最终都派生自Obiect,所以我们可以保证每个类型的实例都有一个这样的 Equals方法。对于那些没有显式重写Equals方法的类型,Obiect(或者重写了Eauals方法的最近的那个基类) 提供的实现将被继承。下面的代码展示了System.Obiect 类型中的Equals 方法实现:

class object {
    public virtual Boolean Equals(0bject obj){
        //如果两个引用指向的是同一个对象
        //它们肯定相等
        if (this == obj)return(true);

        //假定两个对象不相等
        return(false);
    }
    ...
}

        如我们所见,该方法采取的策略可能是最简单的:如果进行比较的两个引用指向的是同一个对象方法将返回true;否则在任何其他情况下,方法都将返回false。如果我们定义了自己的类型,并且希望比较它们中的字段是否相等,Object类型提供的默认实现对我们来说是不够的,我们必须重写Equals方法,提供自己的实现。

        当实现自己的Equals方法时,我们必须确保它遵循以下4条规则:

  • Equals 方法必须是自反的,也就是说,x.Equals(x)必须返回true。
  • Equals 方法必须是对称的,也就是说,x.Equals(y)和y.Equals(x)必须返回同样的值。.
  • Equals 方法必须是可传递的,也就是说,如果x.Equals(y)和y.Equals(z)都返回 true,那么x.Equals(z)也必须返回 true。
  • Equals方法必须是前后一致的,也就是说,如果两个对象的值没有发生改变,多次调用Equals力法的返回值应该相同。

        如果我们为Eguals方法提供的实现没有遵循上述4条规则,我们的应用程序将会发生一些奇怪的不可预期的行为。

        不幸的是,重写 Obiect 的 Equals方法并不如想象的那么容易。我们必须执行许多步操作,并且要保证每一步操作都是正确的。另外,根据我们定义的类型的不同,这些操作也会有一些差别。所幸的是,实现Eguals方法只有3种不同的方式。下面我们逐一讨论每一种模式。

为基类没有重写 Obiect.Eauals 方法的引用类型实现 Eauals

        对于那些直接继承了Obiect的 Equals实现的类型,下面的代码展示了怎样为它们实现 Equals方法:

    //这是一个引用类型('class'的缘故)
    class MyRefType : Baserype
    {
        RefType refobj;    //该字段是一个引用类型
        Valrype valobj;    //该字段是一个值类型

        pubiic override Boolean quals(0bject obj)
        {
            //因为'this'不为null,所以如果obj 为 null,
            //那么两个对象将不可能相等
            if (obj == null) return false;
            //如果两个对象的类型不同,那么它们不可能相等if(this.GetType()!= obj.GetType())return false;
            //将ob〕转型为定义的类型以访问其中的字段。注意这里的转型不会失败,因为已经知道两个对象是同一个类型1/
            MyRefType other = (MyRefrype)obj;

            //比较其中的引用类型字段if (!0bject.Equals(refobj, other.refobj))return false;
            //比较其中的值类型字段
            if (!valobj,Equals(other.valobj))return false;
            return true;//到这里两个对象才算相等
        }

        //重载==和!=操作符(可选)
        public static Boolean operator ==(MyRefrype ol, MyRefrype o2)
        {
            return object.Equals(ol,o2);
        }

        public static Boolean operator !=(MyRefrype ol, MyRefType o2)
        {
            return !(o1 == 02);
        }
    }

        这里实现的 Eguals首先将 obi和 nu相比较。如果被比较的对象不为 null,那么接着比较两个对象的类型。如果两个对象的类型不同,那么它们不可能相等。如果两个对象有着相同的类型,就将obi 转型为 MyRefType,这里的转型不可能抛出异常,因为我们已经知道两个对象为同一个类型。等上述所有步骤都正确执行完毕后,我们才开始比较两个对象中的字段。如果两个对象中所有的字段都相等,方法将返回 true。

        在比较两个对象中的字段时,我们必须非常仔细。前面的代码展示了根据字段类型的不同,所进行的两种不同的比较方式。

比较引用类型的字段

要比较引用类型的字段,我们应该调用Obiect的静态Equals 方法。Object 的静态 Equals方法是一个比较两个引用类型对象的辅助方法。下面展示了 Object 的静态Eguals方法的内部实现:

    public static Boolean Equals(0bject objA, object objB)
    {
        // 如果 objA 和 objB 指向的是同--个对象,方法返回 true
        if (objA == objB)return true;
        // 如果 objA 或者 objB 为nu1l,它们不可能相等,方法返回 false
        if ((objA == null)|l(objB == null))return f
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

「已注销」

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值