zoukankan      html  css  js  c++  java
  • c# 重载运算符(ovveride operator)踩坑记,关于null比对

    场景描述:

    需要比对两个版本的对应对象是否完全一致(每个属性值一致),不一致的导出报表颜色标识,以便提醒后续使用报表人员。

    实现思路:

    对象重载ToString方法,另实现一比对基类(为了通用)重载==与!=运算符,所有比对对象继承于比对基类。

    代码:

    class A:C
        {
            public A(string a, string b)
            {
                AA = a;
                BB = b;
            }
            public string AA { get; set; }
    
            public string BB { get; set; }
    
            public override string ToString()
            {
                return AA+BB; 
            }
        }
    
        class B:C
        {
            public B() { }
            public B(string a, string b)
            {
                AA = a;
                BB = b;
            }
            public string AA { get; set; }
    
            public string BB { get; set; }
    
            public override string ToString()
            {
                return AA + BB;
            }
        }
    
        class C
        {
            public static bool operator ==(C a, C b)
            {
                //这里有漏洞,对象比对,如果是和null比对呢,以下。。。呵呵了
                string _a = a.ToString();
                string _b = b.ToString();
                return _a.Length == _b.Length && _a.GetHashCode() == _b.GetHashCode() && _a == _b;
            }
    
            public static bool operator !=(C a, C b)
            {
                return true;
            }
        }
    
        class Test
        {
            public void Compare()
            {
                Console.WriteLine(new A("a", null) == new A("a", "b"));//正常
                Console.WriteLine(new B("a", "b") == new B("a", "b"));//正常
    
                Console.WriteLine(new B("a", "b") == null);//额,这个是直击漏洞
            }
        }

    怎么解决漏洞呢,第二版C类:

    class C
        {
            public static bool operator ==(C a, C b)
            {
                //这里会死循环System.StackOverflowException异常
                if (a == null || b == null)
                {
                    if (a == b)
                        return true;
                    return false;
                }
                string _a = a.ToString();
                string _b = b.ToString();
                return _a.Length == _b.Length && _a.GetHashCode() == _b.GetHashCode() && _a == _b;
            }
    
            public static bool operator !=(C a, C b)
            {
                return true;
            }
        }

    为什么呢?等抛出异常后,明白了,在判断a==null的时候,不同样需要执行重载后的==吗?一遍一遍的执行,死循环呗。

    思考一下,有没有什么解决办法?如果当前自己写的重载有问题,那能不能用没问题的重载呢?比如所有类的基类object,而object==null是不报异常的,那就考虑第三版,如下:

    class C
        {
            public static bool operator ==(C a, C b)
            {
                //借用object==null来判断,类型转换,耗时
                if ((a as object) == null)
                {
                    return (b as object) == null;
                }
                if ((b as object) == null)
                    return false;
                string _a = a.ToString();
                string _b = b.ToString();
                return _a.Length == _b.Length && _a.GetHashCode() == _b.GetHashCode() && _a == _b;
            }
    
            public static bool operator !=(C a, C b)
            {
                return true;
            }
        }

    我本人不通底层的东西,但是,类型转换确实耗时,我这边报表是几万条数据的比对,当然,我也没测,于是想到一重可以通过is判断类型的思路,如下:

    class C
        {
            public static bool operator ==(C a, C b)
            {
                //借用is判断类型
                if ((a is C) && (b is C))
                {
                    string _a = a.ToString();
                    string _b = b.ToString();
                    return _a.Length == _b.Length && _a.GetHashCode() == _b.GetHashCode() && _a == _b;
                }
                return !(a is C) && !(b is C);
            }
    
            public static bool operator !=(C a, C b)
            {
                return true;
            }
        }

    以上是我的思路,如果哪位大神懂为什么object==null比对是没问题的,还请告知,再次谢过,欢迎大家留言。

    附:!=的判断也不能只返回true,如果你的系统中用到!=去比对。。应修改为如下(只实现一种):

           public static bool operator !=(C a, C b)
            {
                if ((a as object) == null)
                    return (b as object) != null;
                if ((b as object) == null)
                    return true;
                return a != b;
            }
  • 相关阅读:
    Windows XP下 Android开发环境 搭建
    Android程序的入口点
    在eclipse里 新建android项目时 提示找不到proguard.cfg
    64位WIN7系统 下 搭建Android开发环境
    在eclipse里 新建android项目时 提示找不到proguard.cfg
    This Android SDK requires Android Developer Toolkit version 20.0.0 or above
    This Android SDK requires Android Developer Toolkit version 20.0.0 or above
    Android requires compiler compliance level 5.0 or 6.0. Found '1.4' instead
    Windows XP下 Android开发环境 搭建
    Android程序的入口点
  • 原文地址:https://www.cnblogs.com/lcawen/p/8352197.html
Copyright © 2011-2022 走看看