• 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;
            }
  • 相关阅读:
    C#中的扩展方法详解
    MVC Razor模板引擎 @RenderBody、@RenderPage、@RenderSection及Html.RenderPartial、Html.RenderAction
    @html.ActionLink的几种参数格式
    MVC session过期如何处理跳转
    LINQ to SQL和Entity Framework对比与关联
    ASP.Net 更新页面输出缓存的几种方法
    asp.net缓存
    ASP.NET应用程序与页面生命周期
    两种图片延迟加载的方法总结jquery.scrollLoading.js与jquery.lazyload.js
    测试入门知识
  • 原文地址:https://www.cnblogs.com/lcawen/p/8352197.html
Copyright © 2020-2023  润新知