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# 高级
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· C#/.NET/.NET Core技术前沿周刊 | 第 29 期(2025年3.1-3.9)
· 从HTTP原因短语缺失研究HTTP/2和HTTP/3的设计差异