• 集合元素比较


    如果有个类对象的集合,要判断一个对象是不是存在这个集合中,可以用Contains方法判断。但我们都知道这判断是引用。假设这个集合里面存在和这个对象所有的值成员的值都相等的元素,我们就认为这个对象存在于这个集合中,那么我们该如果做? 我能想到就是重写Object基类中的Equals方法,然后为这个集合添加一个扩展方法。如下:

    public class Racer 
     {
            public Racer(string firstName, string lastName, string country = "", int wins = 0)
            {
                this.FirstName = firstName;
                this.LastName = lastName;
                this.Country = country;
                this.Wins = wins;   
            }
    
            public string FirstName { get; private set; }
    
            public string LastName { get; private set; }
    
            public string Country { get; private set; }
    
            public int Wins { get; private set; }
    
            public override bool Equals(object obj)
            {
                Racer other = obj as Racer;
                if (other == null)
                    return false;
    
                return FirstName == other.FirstName
                    && LastName == other.LastName
                    && Country == other.Country
                    && Wins == other.Wins;
            }
    
      }

    List<Racer>的扩展方式:

    public static bool HasItem(this List<Racer> listR, Racer racer)
            {
                return listR.Any(x => x.Equals(racer));
            }

    然后我们就可以调用HasItem判断,测试一下:

    List<Racer> listRacer = new List<Racer>();
                listRacer.Add(new Racer("xixiao", "meng","china"));
                listRacer.Add(new Racer("zhstar", "zhou","china"));
                
                Racer racer = new Racer("zhstar", "zhou","china");
    
                Console.WriteLine("listRacer HasItem racer:{0}", listRacer.HasItem(racer));
                Console.WriteLine("listRacer Contains racer:{0}", listRacer.Contains(racer));

    运行代码代码我们发现HasItem方法和Contains方法都返回了True。这是为什么呢?跟踪调试发现,原来Contains方法也是通过我们重写的Equals方法来判断的。原来如此,于是我们可以删掉扩展方法直接使用系统的Contains方法了。那是不是Contains的判断一定就是调用基类中Equals方法呢?

    我们修改一下Racer类,让它集成IEquatable接口,实现Equals方法,让它返回引用比较的结果:

    View Code
    public class Racer :IEquatable<Racer>
        {
            public Racer(string firstName, string lastName, string country = "", int wins = 0)
            {
                this.FirstName = firstName;
                this.LastName = lastName;
                this.Country = country;
                this.Wins = wins;   
            }
    
            public string FirstName { get; private set; }
    
            public string LastName { get; private set; }
    
            public string Country { get; private set; }
    
            public int Wins { get; private set; }
    
            public override bool Equals(object obj)
            {
                Racer other = obj as Racer;
                if (other == null)
                    return false;
    
                return FirstName == other.FirstName
                    && LastName == other.LastName
                    && Country == other.Country
                    && Wins == other.Wins;
            }
    
            public bool Equals(Racer other)
            {
                return object.ReferenceEquals(this, other);
            }
        }

    在按照前面那样测试一下Contains和HasItem方法,我们会发现返回的结果都是false。这是不是说明了对于Equals方法,如果实现了IEquatable接口,那么会首先使用这个接口的Equals方法,如果没有实现这个接口就会使用基类的或者重写基类的Equals方法呢?

    我们再修改一下Racer类,把IEquatable接口去掉,但保留Equals方法:

    View Code
    public class Racer
        {
            public Racer(string firstName, string lastName, string country = "", int wins = 0)
            {
                this.FirstName = firstName;
                this.LastName = lastName;
                this.Country = country;
                this.Wins = wins;   
            }
    
            public string FirstName { get; private set; }
    
            public string LastName { get; private set; }
    
            public string Country { get; private set; }
    
            public int Wins { get; private set; }
    
            public override bool Equals(object obj)
            {
                Racer other = obj as Racer;
                if (other == null)
                    return false;
    
                return FirstName == other.FirstName
                    && LastName == other.LastName
                    && Country == other.Country
                    && Wins == other.Wins;
            }
    
            public bool Equals(Racer other)
            {
                return object.ReferenceEquals(this, other);
            }
        }

    再运行一下,会发现HasItem方法返回了false,但Contains方法却返回True。

    到这里,其实就很明白,对集合来说,它是一个泛型的类,无法知道每个类型具体的成员,在判断一个元素或者查找一个元素的时候,首先依赖的是IEquatable接口的Equals方法,如果没有继承这个接口那么就使用基类中的Equals方法。但我们在调用对象实例里面的方法,它就会找到那个最适合被调用的方法。比如上面的例子中如果我们把扩展方法的第二个参数该成object类型,就会调用我们重写的基类的Equals方法。

  • 相关阅读:
    JS单例对象与构造函数对象的区别
    SVG系列
    Js极客之路
    Js极客之路
    iOS微信登录
    iOS HSV
    cocoa pods
    php中请求数据中文乱码
    付费中数字计算
    时间戳对应关系
  • 原文地址:https://www.cnblogs.com/zhstar/p/2659222.html
Copyright © 2020-2023  润新知