zoukankan      html  css  js  c++  java
  • 集合元素比较

    如果有个类对象的集合,要判断一个对象是不是存在这个集合中,可以用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方法。

  • 相关阅读:
    前后端分离实践 — 如何解决跨域问题
    bower 和 npm 的区别详细介绍
    yeoman-bower-grunt之间的关系
    软件开发环境-开发环境、测试环境、生产环境的区别
    Tomcat下配置JNDI的三种方式
    SSE
    Java动态代理
    Css之Relative
    多线程之——死锁
    JVM
  • 原文地址:https://www.cnblogs.com/zhstar/p/2659222.html
Copyright © 2011-2022 走看看