场景描述:

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

实现思路:

对象重载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# 重载运算符(ovveride operator)踩坑记,关于null比对的更多相关文章

  1. Spark踩坑记——Spark Streaming+Kafka

    [TOC] 前言 在WeTest舆情项目中,需要对每天千万级的游戏评论信息进行词频统计,在生产者一端,我们将数据按照每天的拉取时间存入了Kafka当中,而在消费者一端,我们利用了spark strea ...

  2. Spark踩坑记——数据库(Hbase+Mysql)

    [TOC] 前言 在使用Spark Streaming的过程中对于计算产生结果的进行持久化时,我们往往需要操作数据库,去统计或者改变一些值.最近一个实时消费者处理任务,在使用spark streami ...

  3. 【踩坑记】从HybridApp到ReactNative

    前言 随着移动互联网的兴起,Webapp开始大行其道.大概在15年下半年的时候我接触到了HybridApp.因为当时还没毕业嘛,所以并不清楚自己未来的方向,所以就投入了HybridApp的怀抱. Hy ...

  4. Spark踩坑记——共享变量

    [TOC] 前言 Spark踩坑记--初试 Spark踩坑记--数据库(Hbase+Mysql) Spark踩坑记--Spark Streaming+kafka应用及调优 在前面总结的几篇spark踩 ...

  5. Spark踩坑记——从RDD看集群调度

    [TOC] 前言 在Spark的使用中,性能的调优配置过程中,查阅了很多资料,之前自己总结过两篇小博文Spark踩坑记--初试和Spark踩坑记--数据库(Hbase+Mysql),第一篇概况的归纳了 ...

  6. djangorestframework+vue-cli+axios,为axios添加token作为headers踩坑记

    情况是这样的,项目用的restful规范,后端用的django+djangorestframework,前端用的vue-cli框架+webpack,前端与后端交互用的axios,然后再用户登录之后,a ...

  7. HttpWebRequest 改为 HttpClient 踩坑记-请求头设置

    HttpWebRequest 改为 HttpClient 踩坑记-请求头设置 Intro 这两天改了一个项目,原来的项目是.net framework 项目,里面处理 HTTP 请求使用的是 WebR ...

  8. vue踩坑记

    vue踩坑记 易错点 语法好难啊qwq 不要把'data'写成'date' 在v-html/v-bind中使用vue变量时不需要加变量名 在非vue事件中使用vue中变量时需要加变量名 正确 < ...

  9. 【bug记录】OS Lab4 踩坑记

    OS Lab4 踩坑记 Lab4在之前Lab3的基础上,增加了系统调用,难度增加了很多.而且加上注释不详细,开玩笑的指导书,自己做起来困难较大.也遇到了大大小小的bug,调试了一整天. 本文记录笔者在 ...

  10. 【bug记录】OS Lab3 踩坑记

    OS Lab3 踩坑记 Lab3在之前Lab2的基础上,增加了进程建立.调度和中断异常处理.其中测试包括进程建立以及进程调度部分. 由于是第一次做bug记录,而且是调试完bug后再做的记录,所以导致记 ...

随机推荐

  1. 转 Maven常用仓库地址以及手动添加jar包到仓库

    转自:http://blog.csdn.net/kqygww/article/details/12837783 共有的仓库 http://repository.sonatype.org/content ...

  2. Android内存泄漏第一课【转】--------(使用单例模式造成的内存泄漏)

    使用单例模式造成的内存泄漏 Android的单例模式在我们项目开发中经常会用到,不过使用的不恰当的话也会造成内存泄漏.因为单例的静态特性使得单例的生命周期和应用的生命周期一样长, 这就说明了如果一个对 ...

  3. 【Java】JDBCUtil模板

    package jdbc; import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; ...

  4. BZOJ5011 JXOI2017颜色(主席树)

    相当于求满足在子段中出现的颜色只在该子段中出现的非空子段数量.这也就相当于其中出现的颜色最左出现的位置在左端点右侧,最右出现的位置在右端点左侧.那么若固定某个端点,仅考虑对该端点的限制,会有一段合法区 ...

  5. Guardian of Decency UVALive - 3415(最大独立集板题)

    老师在选择一些学生做活动时,为避免学生发生暧昧关系,就提出了四个要求.在他眼中,只要任意两个人符合这四个要求之一,就不可能发生暧昧.现在给出n个学生关于这四个要求的信息,求老师可以挑选出的最大学生数量 ...

  6. Javascript面向对象三大特性(封装性、继承性、多态性)详解及创建对象的各种方法

    Javascript基于对象的三大特征和C++,Java面向对象的三大特征一样,都是封装(encapsulation).继承(inheritance )和多态(polymorphism ).只不过实现 ...

  7. 【刷题】BZOJ 2753 [SCOI2012]滑雪与时间胶囊

    Description a180285非常喜欢滑雪.他来到一座雪山,这里分布着M条供滑行的轨道和N个轨道之间的交点(同时也是景点),而且每个景点都有一编号i(1<=i<=N)和一高度Hi. ...

  8. Ajax请求会话过期处理(JS)

    对于页面来说,处理session过期比较简单,一般只需在过滤器里面判断session用户是否存在,不存在则跳转页面到登陆页即可. 对于Ajax请求来说,这个办法则无效,只能获取到登录页的html代码. ...

  9. 【BZOJ3156】防御准备(动态规划,斜率优化)

    [BZOJ3156]防御准备(动态规划,斜率优化) 题面 BZOJ 题解 从右往左好烦啊,直接\(reverse\)一下再看题. 设\(f[i]\)表示第\(i\)个位置强制建立检查站时,前面都满足条 ...

  10. 20135239 益西拉姆 linux内核分析 使用库函数API和C代码中嵌入汇编代码两种方式使用同一个系统调用

    https://drive.wps.cn/preview#l/759e32d65654419cb765da932cdf5cdc 本次直接在wps上写的,因为不能连同图片一起粘贴过来,一个一个粘比较费时 ...