内容简介:在微软的官方文档中,规定本文将介绍重载方法和原理。感谢在微软的官方文档
在微软的官方文档中,规定 &&
和 ||
运算符不可被重载,但允许通过重载 &
、 |
、 true
和 false
实现间接重载。
本文将介绍重载方法和原理。感谢 Opportunity 的指导。
条件逻辑运算符是可以重载的
在微软的官方文档 true Operator (C# Reference) - Microsoft Docs 中,解释了 &&
和 ||
这两个条件逻辑运算符的重载方法:
A type cannot directly overload the Caseal logical operators (&& and | ), but an equivalent effect can be achieved by overloading the regular logical operators and operators true and false. |
类型不能直接重载条件逻辑运算符(&& 和 | ),但通过重载常规逻辑运算符 &、 | 及运算符 true 和 false 可以达到同样的效果。 |
也就是说,在官方的概念中, &&
和 ||
是允许被重载的,只是不能直接重载。
原因在于, &&
和 ||
是短路运算符(Circuit Operator),具有短路求值特性。具体来说, A && B
运算中,如果 A
是 false
,那么 B
的值便不会计算;同样的, A || B
中,如果 A
是 true
,那么 B
的值也不会计算。
于是,如果允许自定义 &&
和 ||
运算符,那么必然会导致这个运算符重载的方法有两个参数传入,于是这两个参数一定会被计算值;这样就无法实现短路求值了。于是对于 &&
和 ||
的重载采用的方案是重载 &
和 |
运算符,然后重载 true
和 false
运算符来指定短路求值。
试错实验
我们写一个类型进行实验:
using System; namespace Walterlv.Demo { public class Case { public static bool operator &(Case a, Case b) { throw new NotImplementedException(); } } }
直接使用 &
是没有问题的,但如果使用 &&
就会提示错误。
var a = new Case(); var b = new Case(); if (a && b) { }
Error CS0217: In order to be applicable as a short circuit operator a user-defined logical operator (‘Case.operator &(Case, Case)’) must have the same return type and parameter types Error CS0217: 为了可以像短路运算符一样应用,用户定义的逻辑运算符(“aa.operator &(aa, aa)”)的返回类型和参数类型必须相同
也就是说,本身重载 &
运算符的时候允许返回不同的类型;但如果希望 &&
运算符在此重载下也生效,就必须确保 &
的返回类型与参数中的类型相同。
public static Case operator &(Case a, Case b) { throw new NotImplementedException(); }
var a = new Case(); var b = new Case(); var c = a && b;
改为相同的类型后,还会继续提示需要定义 true
和 false
运算符。
Error CS0218: In order for ‘Case.operator &(Case, Case)’ to be applicable as a short circuit operator, its declaring type ‘Case’ must define operator true and operator false
重载 && 和 ||
以下代码中, true
表示字符串中包含大写字母, false
表示字符串中不包含大写字母( null
和没有大小写的区域也属于不包含大写字母)。 &
运算符仅留下两者共有的字符; |
则取所有字符。
public class Case { private string _value; public Case(string value) { _value = value; } public static Case operator &(Case a, Case b) { if (a is null || b is null) return null; if (a._value is null || b._value is null) return new Case(null); return new Case(new string(b._value.Except(a._value.Except(b._value)).ToArray())); } public static Case operator |(Case a, Case b) => new Case(a._value + b._value); public static bool operator true(Case a) => a?._value != null && !a._value.ToLower(CultureInfo.CurrentCulture).Equals(a._value); public static bool operator false(Case a) => a?._value == null || a._value.ToLower(CultureInfo.CurrentCulture).Equals(a._value); public override string ToString() => _value; }
测试重载了条件逻辑运算符的类型
我们测试以上代码所用的代码如下:
var a = new Case("A"); var b = new Case("b"); Console.WriteLine(a); Console.WriteLine(b); Console.WriteLine(a ? "a 是 truthy" : "a 是 falsy"); Console.WriteLine(b ? "b 是 truthy" : "b 是 falsy"); Console.WriteLine(a & b); Console.WriteLine(a | b); Console.WriteLine(a && b); Console.WriteLine(a || b);
以上各个 Console.WriteLine
的输出为:
[1] A [2] b [3] a 是 truthy [4] b 是 falsy [5] [6] Ab [7] [8] A
注意,空行其实指的是输出 null
。
truthy 和 falsy
刚刚的测试代码中,我们使用了 truthy 和 falsy 概念,而这是逻辑判断概念:
- 如果在逻辑判断中,对象与
true
等价,但其数值上并非true
(不等于true
),那么称此对象为 truthy; - 如果在逻辑判断中,对象与
false
等价,但其数值上并非false
(不等于false
),那么称此对象为 falsy。
对以上测试输出的解释
第 5 行由于 a
和 b
没有共有字符,所以得到 null
。
第 7 行的执行过程是这样的:
- 对
a
求值,即a
本身; - 对
a
进行 truthy / falsy 逻辑判断,得到 truthy; - 由于
a
为 truthy,对于&&
运算符而言,可以对 b 求值,于是对b
求值得到b
本身; - 对
a
和b
进行&
运算,得到 `,也就是
null`。
第 8 行的执行过程是这样的:
- 对
a
求值,即a
本身; - 对
a
进行 truthy / falsy 逻辑判断,得到 truthy; - 由于
a
为 truthy,对于||
运算符而言,已无需对b
求值,最终得到的结果为a
,也就是A
。
参考资料
- C# 中那些可以被重载的操作符 - walterlv - 请阅读文章末尾的评论
- true Operator (C# Reference) - Microsoft Docs
- JavaScript: Truthy? Falsy? - 格物致知
本文会经常更新,请阅读原文: https://walterlv.com/post/overload-conditional-and-and-or-operators-in-csharp.html ,以避免陈旧错误知识的误导,同时有更好的阅读体验。
本作品采用 知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议 进行许可。欢迎转载、使用、重新发布,但务必保留文章署名 吕毅 (包含链接:https://walterlv.com ),不得用于商业目的,基于本文修改后的作品务必以相同的许可发布。如有任何疑问,请 与我联系 (walter.lv@qq.com) 。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:- C++ 运算符重载讲解与经典实例
- 功能编程 – Clojure中的运算符重载
- [短文速读] 重载有暗坑,重载重写你真的了解么
- C# 空合并操作符(??)不可重载?其实有黑科技可以间接重载!
- SPL 数组重载
- SPL 数组重载
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。