场景描述:

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

实现思路:

对象重载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. Varnish是一款高性能的开源HTTP加速器

    如何衡量缓存系统的优劣性 1:缓存命中率: 在memcached服务器中,get_hits的值表示缓存命中的次数,get_misses的值表示没有命中的次数,那么命中率的计算公式就是:命中率=get_ ...

  2. Webservice开发概念

    一.Web Service基本概念 Web Service由两部分组成 SOAP--Web Service之间的基本通信协议. WSDL--Web Service描述语言,它定义了Web Servic ...

  3. Cmder命令行工具在Windows系统中的配置

    一.Cmder简介 Cmder:一款用于Windows系统中,可增强传统cmd命令行工具的控制台模拟器(类似于Linux系统中的终端控制窗口) 特点: 无需安装,解压即用 可使用较多Linux命令,如 ...

  4. application/x-www-form-urlencoded 与 application/json区别

    两种请求方式对服务器端都没什么影响 application/x-www-form-urlencoded方式是比较老的一种方式,这种方式的好处就是浏览器都支持, 在请求发送过程中会对数据进行序列化处理, ...

  5. oracle 数据库 命令

    SQL PLUS 命令: SELECT * FROM ALL_TABLES;系统里有权限的表SELECT * FROM DBA_TABLES; 系统表SELECT * FROM USER_TABLES ...

  6. 【UNIX环境高级编程】线程同步

    当多个线程共享相同的内存时,需要确保每个线程看到一致的数据视图.如果每个线程使用的变量都是其他线程不会读取和修改的,那么就不存在一致性问题.同样,如果变量是只读的也不会有一致性问题.但是,当一个线程可 ...

  7. ie浏览器升级的正确姿势

    一.版本说明 1.当前IE浏览器分为一下几个版本:IE 6,IE 7,IE 8,IE 9,IE 10,IE 11 2.windows最高支持IE版本win xp:IE 8win 7 :IE 11win ...

  8. 【.Net】win10 uwp unix timestamp 时间戳 转 DateTime

    有时候需要把网络的 unix timestamp 转为 C# 的 DateTime ,在 UWP 可以如何转换? 转换函数可以使用下面的代码 private static DateTime UnixT ...

  9. 【Java】CSVUtils

    package com.msk.ds.logic; import java.io.*; import java.util.List; /** * Created by Administrator on ...

  10. 【BZOJ2138】stone(线段树,Hall定理)

    [BZOJ2138]stone(线段树,Hall定理) 题面 BZOJ 题解 考虑一个暴力. 我们对于每堆石子和每个询问,显然是匹配的操作. 所以可以把石子拆成\(a_i\)个,询问点拆成\(K_i\ ...