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;
        }
原文地址:https://www.cnblogs.com/lcawen/p/8352197.html