1先试试:两个盒子能直接相加吗
Box 类表示一个盒子,有长、宽、高三项数据。什么都不准备,直接写 Box1 + Box2:
| 60 | Box3 = Box1 + Box2; | // Box 里没写 operator+,编译器不知道两个盒子怎么加 |
Program.cs(60,17): error CS0019: 运算符“+”无法应用于“Box”和“Box”类型的操作数
int、double 的加法早就定义好了,可两个盒子怎么加,编译器不知道。得由我们自己告诉它,这就是运算符重载。
2运算符重载怎么写
内置类型(比如 int)的运算符是改不了的,我们能做的是给自己写的类型定义运算符的含义。重载运算符其实就是一个方法,名字很特别:关键字 operator 后面紧跟运算符的符号;它也有返回类型和参数列表,前面的 public 和 static 都不能少。
| 30 | public static Box operator+ (Box b, Box c) | // operator+:b 是加号左边的盒子,c 是右边的 |
| 31 | { | // operator+ 开始 |
| 32 | Box box = new Box(); | // new 一个新盒子,用来装结果 |
| 33 | box.length = b.length + c.length; | // 长相加:6 + 12 = 18 |
| 34 | box.breadth = b.breadth + c.breadth; | // 宽相加:7 + 13 = 20 |
| 35 | box.height = b.height + c.height; | // 高相加:5 + 10 = 15 |
| 36 | return box; | // 返回新盒子 (18, 20, 15);b 和 c 一点没变 |
以 Box1 (6, 7, 5) 加 Box2 (12, 13, 10) 为例,可以把它想成一台拼接台:长、宽、高各加各的,放进新盒子。原来的两个盒子一点都没变,加号给的是一个新盒子。
public 和 static 不能少
把 static 去掉,编译器就报错:
| 30 | public Box operator+ (Box b, Box c) | // 去掉了 static,只剩 public |
Program.cs(30,26): error CS0558: User-defined operator 'Box.operator +(Box, Box)' must be declared static and public
改不了 int 的加法
在 Box 里写一个加号,两个参数都是 int:
| 29 | public static int operator+ (int a, int b) | // 想改 int 的加法:两个参数都是 int,让 + 变成减法 |
| 30 | { | // operator+(int, int) 开始 |
| 31 | return a - b; | // 做减法 |
| 32 | } | // operator+(int, int) 结束 |
Program.cs(29,33): error CS0563: 二元运算符的参数之一必须是包含类型
二元运算符的参数里,至少要有一个是包含类型(写这个运算符的那个类),在这里就是 Box。所以 int 加 int 的规则,谁也改不了。
3完整程序
Box 有三个私有字段和三个 set 方法,getVolume 算体积,operator+ 也写在 Box 类里面。长宽高是私有的,operator+ 为什么能读 b 和 c 的字段?因为 private 管的是整个类,同一个类里的代码都能访问。
| 69 | Box3 = Box1 + Box2; | // 调用 operator+(Box1, Box2),Box3 拿到新盒子 |
| 70 | | |
| 71 | // Box3 的体积 | |
| 72 | volume = Box3.getVolume(); | // 18 × 20 × 15 = 5400 |
| 73 | Console.WriteLine("Box3 的体积: {0}", volume); | // 输出 5400,不是 210 + 1560 |
查看完整代码(77 行)
| 1 | using System; | // 引入 System 命名空间(Console 在里面) |
| 2 | | |
| 3 | namespace OperatorOvlApplication | // 定义命名空间 OperatorOvlApplication |
| 4 | { | // 命名空间 OperatorOvlApplication 开始 |
| 5 | class Box | // 定义 Box 类:表示一个盒子 |
| 6 | { | // Box 类开始 |
| 7 | private double length; // 长度 | // 私有字段:长 |
| 8 | private double breadth; // 宽度 | // 私有字段:宽 |
| 9 | private double height; // 高度 | // 私有字段:高 |
| 10 | | |
| 11 | public double getVolume() | // getVolume:算体积 |
| 12 | { | // getVolume 开始 |
| 13 | return length * breadth * height; | // 长 × 宽 × 高 |
| 14 | } | // getVolume 结束 |
| 15 | public void setLength( double len ) | // setLength:设置长 |
| 16 | { | // setLength 开始 |
| 17 | length = len; | // 把参数 len 存进 length |
| 18 | } | // setLength 结束 |
| 19 | | |
| 20 | public void setBreadth( double bre ) | // setBreadth:设置宽 |
| 21 | { | // setBreadth 开始 |
| 22 | breadth = bre; | // 把参数 bre 存进 breadth |
| 23 | } | // setBreadth 结束 |
| 24 | | |
| 25 | public void setHeight( double hei ) | // setHeight:设置高 |
| 26 | { | // setHeight 开始 |
| 27 | height = hei; | // 把参数 hei 存进 height |
| 28 | } | // setHeight 结束 |
| 29 | // 重载 + 运算符来把两个 Box 对象相加 | |
| 30 | public static Box operator+ (Box b, Box c) | // operator+:b 是加号左边的盒子,c 是右边的 |
| 31 | { | // operator+ 开始 |
| 32 | Box box = new Box(); | // new 一个新盒子,用来装结果 |
| 33 | box.length = b.length + c.length; | // 长相加:6 + 12 = 18 |
| 34 | box.breadth = b.breadth + c.breadth; | // 宽相加:7 + 13 = 20 |
| 35 | box.height = b.height + c.height; | // 高相加:5 + 10 = 15 |
| 36 | return box; | // 返回新盒子 (18, 20, 15);b 和 c 一点没变 |
| 37 | } | // operator+ 结束 |
| 38 | | |
| 39 | } | // Box 类结束 |
| 40 | | |
| 41 | class Tester | // 定义 Tester 类,放 Main |
| 42 | { | // Tester 类开始 |
| 43 | static void Main(string[] args) | // 程序入口 Main 方法 |
| 44 | { | // Main 开始 |
| 45 | Box Box1 = new Box(); // 声明 Box1,类型为 Box | // 创建第一个盒子 |
| 46 | Box Box2 = new Box(); // 声明 Box2,类型为 Box | // 创建第二个盒子 |
| 47 | Box Box3 = new Box(); // 声明 Box3,类型为 Box | // Box3 先随便 new 一个,后面会换成相加的结果 |
| 48 | double volume = 0.0; // 体积 | // 用来存体积 |
| 49 | | |
| 50 | // Box1 详述 | |
| 51 | Box1.setLength(6.0); | // Box1 的长 = 6 |
| 52 | Box1.setBreadth(7.0); | // Box1 的宽 = 7 |
| 53 | Box1.setHeight(5.0); | // Box1 的高 = 5 |
| 54 | | |
| 55 | // Box2 详述 | |
| 56 | Box2.setLength(12.0); | // Box2 的长 = 12 |
| 57 | Box2.setBreadth(13.0); | // Box2 的宽 = 13 |
| 58 | Box2.setHeight(10.0); | // Box2 的高 = 10 |
| 59 | | |
| 60 | // Box1 的体积 | |
| 61 | volume = Box1.getVolume(); | // 6 × 7 × 5 = 210 |
| 62 | Console.WriteLine("Box1 的体积: {0}", volume); | // {0} 处填入 volume,输出 210 |
| 63 | | |
| 64 | // Box2 的体积 | |
| 65 | volume = Box2.getVolume(); | // 12 × 13 × 10 = 1560 |
| 66 | Console.WriteLine("Box2 的体积: {0}", volume); | // 输出 1560 |
| 67 | | |
| 68 | // 把两个对象相加 | |
| 69 | Box3 = Box1 + Box2; | // 调用 operator+(Box1, Box2),Box3 拿到新盒子 |
| 70 | | |
| 71 | // Box3 的体积 | |
| 72 | volume = Box3.getVolume(); | // 18 × 20 × 15 = 5400 |
| 73 | Console.WriteLine("Box3 的体积: {0}", volume); | // 输出 5400,不是 210 + 1560 |
| 74 | Console.ReadKey(); | // 等待按键(现在的 VS 不写也会停住) |
| 75 | } | // Main 结束 |
| 76 | } | // Tester 类结束 |
| 77 | } | // 命名空间结束 |
Box1 的体积: 210 Box2 的体积: 1560 Box3 的体积: 5400
很多人会猜 Box3 的体积是 210 + 1560 = 1770,实际是 5400:我们的加号加的是长、宽、高,不是体积。Box3 的长宽高是 18、20、15,乘起来正好 5400。加号到底做什么,全看方法里怎么写。
4哪些运算符能重载
- 一元运算符(只有一个操作数,操作数就是参与运算的值):
+-!~++--,还有true和false,都能重载。 - 二元运算符(有两个操作数):
+-*/%,还有与&、或|、异或^、左移<<、右移>>,都能重载。 - 比较运算符:
==!=<><=>=能重载,但必须成对写:写了==就得写!=,写了<就得写>,<=和>=也一样。
只留 ==、删掉 !=:
| 39 | public static bool operator == (Box lhs, Box rhs) | // 只写了 ==,下面没写 != |
Program.cs(39,35): error CS0216: 运算符“Box.operator ==(Box, Box)”要求也要定义匹配的运算符“!=”
5哪些不能重载
&& 和 ||
并且 &&、或者 || 这两个条件运算符不能直接重载:
| 29 | public static Box operator&& (Box b, Box c) | // 想重载 &&(并且) |
| 30 | { | // operator&& 开始 |
| 31 | return b; | // 随便返回左边的盒子 |
| 32 | } | // operator&& 结束 |
Program.cs(29,33): error CS1020: 应输入可重载的二元运算符
想让它们能用,要改为重载 &、|,再加上 true 和 false。
+= 这类复合赋值
+=、-= 这类复合赋值(先算再赋值回去)不用单独写:只要重载了 +,+= 就自动能用。
| 69 | Box3 = Box1; | // Box3 先指向 Box1 这个盒子 |
| 70 | Box3 += Box2; | // 等于 Box3 = Box3 + Box2,得到 (18, 20, 15) |
运行结果和上面一样,Box3 的体积还是 5400,因为 += 用的就是我们写的加号。
从 C# 14(.NET 10) 开始,+= 也能自己写(教程说它不能重载,这个说法已过时)。它不带 static,返回 void,直接改左边那个盒子:
| 29 | public void operator+= (Box c) | // 不带 static、返回 void,参数 c 是右边的盒子 |
| 30 | { | // operator+= 开始 |
| 31 | length += c.length; | // 直接改左边这个盒子自己的长:加上 c 的长 |
| 32 | breadth += c.breadth; | // 宽也加上 c 的宽 |
| 33 | height += c.height; | // 高也加上 c 的高 |
| 34 | } | // operator+= 结束 |
这段代码用 .NET 10 编译通过,Box3 的体积还是 5400;换成 .NET 9 就报错:
Program.cs(29,27): error CS1019: 应输入可重载的一元运算符
完全不能重载的
赋值 =、点 .、?:、->、new、is、sizeof、typeof,这些都不能重载。
6扩展实例:重载比较运算符
==:长、宽、高都相等,才返回 true。!= 正好反过来,只要有一项不相等就返回 true。
| 39 | public static bool operator == (Box lhs, Box rhs) | // 重载 ==:返回 bool(true 或 false) |
| 40 | { | // operator == 开始 |
| 41 | bool status = false; | // 先假设结果是 false |
| 42 | if (lhs.length == rhs.length && lhs.height == rhs.height | // 长、高相等,&& 表示“并且”…… |
| 43 | && lhs.breadth == rhs.breadth) | // ……宽也相等,三项全相等才成立 |
| 44 | { | // if 开始 |
| 45 | status = true; | // 条件成立,结果改成 true |
| 46 | } | // if 结束 |
| 47 | return status; | // 返回比较结果 |
| 48 | } | // operator == 结束 |
< 要求三项都更小,> 要求三项都更大,<=、>= 也一样要三项都满足:
| 59 | public static bool operator <(Box lhs, Box rhs) | // 重载 <:返回 bool(true 或 false) |
| 60 | { | // operator < 开始 |
| 61 | bool status = false; | // 先假设结果是 false |
| 62 | if (lhs.length < rhs.length && lhs.height | // 长更小、高也更小…… |
| 63 | < rhs.height && lhs.breadth < rhs.breadth) | // ……宽也更小,三项都更小才成立 |
| 64 | { | // if 开始 |
| 65 | status = true; | // 条件成立,结果改成 true |
| 66 | } | // if 结束 |
| 67 | return status; | // 返回比较结果 |
| 68 | } | // operator < 结束 |
还有一个 ToString 方法,把盒子写成括号里的三个数。它前面写的是 override,这是上一节讲的重写,不是重载(教程注释里写成了“重载”)。
| 102 | public override string ToString() | // override 是重写(上一节讲的),不是重载 |
| 103 | { | // ToString 开始 |
| 104 | return String.Format("({0}, {1}, {2})", length, breadth, height); | // 把长宽高拼成 (长, 宽, 高) 这样的文字 |
| 105 | } | // ToString 结束 |
拿 Box1 (6, 7, 5) 和 Box2 (12, 13, 10) 比:Box1 < Box2 时 6 比 12、7 比 13、5 比 10 三项都更小,结果 true;Box1 >= Box2 三项都不满足,结果 false。
| 157 | if (Box1 >= Box2) | // 调用 operator >=:三项都不满足,结果 false |
| 158 | Console.WriteLine("Box1 大于等于 Box2"); | // 条件成立时输出这句(这次不走) |
| 159 | else | // 否则 |
| 160 | Console.WriteLine("Box1 不大于等于 Box2"); | // 输出 Box1 不大于等于 Box2 |
最后一行 Box3 等于 Box4:前面让 Box4 指向了 Box3,两个变量其实是同一个盒子,长宽高当然都相等。
| 169 | Box4 = Box3; | // Box4 改成指向 Box3 那个盒子:两个变量,同一个盒子 |
| 170 | if (Box3 == Box4) | // 调用 operator ==:同一个盒子,长宽高当然都相等,结果 true |
| 171 | Console.WriteLine("Box3 等于 Box4"); | // 输出 Box3 等于 Box4 |
查看完整代码(178 行)
| 1 | using System; | // 引入 System 命名空间(Console 在里面) |
| 2 | | |
| 3 | namespace OperatorOvlApplication | // 定义命名空间 OperatorOvlApplication |
| 4 | { | // 命名空间 OperatorOvlApplication 开始 |
| 5 | class Box | // 定义 Box 类:表示一个盒子 |
| 6 | { | // Box 类开始 |
| 7 | private double length; // 长度 | // 私有字段:长 |
| 8 | private double breadth; // 宽度 | // 私有字段:宽 |
| 9 | private double height; // 高度 | // 私有字段:高 |
| 10 | | |
| 11 | public double getVolume() | // getVolume:算体积 |
| 12 | { | // getVolume 开始 |
| 13 | return length * breadth * height; | // 长 × 宽 × 高 |
| 14 | } | // getVolume 结束 |
| 15 | public void setLength( double len ) | // setLength:设置长 |
| 16 | { | // setLength 开始 |
| 17 | length = len; | // 把参数 len 存进 length |
| 18 | } | // setLength 结束 |
| 19 | | |
| 20 | public void setBreadth( double bre ) | // setBreadth:设置宽 |
| 21 | { | // setBreadth 开始 |
| 22 | breadth = bre; | // 把参数 bre 存进 breadth |
| 23 | } | // setBreadth 结束 |
| 24 | | |
| 25 | public void setHeight( double hei ) | // setHeight:设置高 |
| 26 | { | // setHeight 开始 |
| 27 | height = hei; | // 把参数 hei 存进 height |
| 28 | } | // setHeight 结束 |
| 29 | // 重载 + 运算符来把两个 Box 对象相加 | |
| 30 | public static Box operator+ (Box b, Box c) | // operator+:b 是加号左边的盒子,c 是右边的 |
| 31 | { | // operator+ 开始 |
| 32 | Box box = new Box(); | // new 一个新盒子,用来装结果 |
| 33 | box.length = b.length + c.length; | // 长相加:6 + 12 = 18 |
| 34 | box.breadth = b.breadth + c.breadth; | // 宽相加:7 + 13 = 20 |
| 35 | box.height = b.height + c.height; | // 高相加:5 + 10 = 15 |
| 36 | return box; | // 返回新盒子 (18, 20, 15);b 和 c 一点没变 |
| 37 | } | // operator+ 结束 |
| 38 | | |
| 39 | public static bool operator == (Box lhs, Box rhs) | // 重载 ==:返回 bool(true 或 false) |
| 40 | { | // operator == 开始 |
| 41 | bool status = false; | // 先假设结果是 false |
| 42 | if (lhs.length == rhs.length && lhs.height == rhs.height | // 长、高相等,&& 表示“并且”…… |
| 43 | && lhs.breadth == rhs.breadth) | // ……宽也相等,三项全相等才成立 |
| 44 | { | // if 开始 |
| 45 | status = true; | // 条件成立,结果改成 true |
| 46 | } | // if 结束 |
| 47 | return status; | // 返回比较结果 |
| 48 | } | // operator == 结束 |
| 49 | public static bool operator !=(Box lhs, Box rhs) | // 重载 !=:返回 bool(true 或 false) |
| 50 | { | // operator != 开始 |
| 51 | bool status = false; | // 先假设结果是 false |
| 52 | if (lhs.length != rhs.length || lhs.height != rhs.height | // || 表示“或者”:长或高有一项不等…… |
| 53 | || lhs.breadth != rhs.breadth) | // ……或宽不等,只要一项不等就成立 |
| 54 | { | // if 开始 |
| 55 | status = true; | // 条件成立,结果改成 true |
| 56 | } | // if 结束 |
| 57 | return status; | // 返回比较结果 |
| 58 | } | // operator != 结束 |
| 59 | public static bool operator <(Box lhs, Box rhs) | // 重载 <:返回 bool(true 或 false) |
| 60 | { | // operator < 开始 |
| 61 | bool status = false; | // 先假设结果是 false |
| 62 | if (lhs.length < rhs.length && lhs.height | // 长更小、高也更小…… |
| 63 | < rhs.height && lhs.breadth < rhs.breadth) | // ……宽也更小,三项都更小才成立 |
| 64 | { | // if 开始 |
| 65 | status = true; | // 条件成立,结果改成 true |
| 66 | } | // if 结束 |
| 67 | return status; | // 返回比较结果 |
| 68 | } | // operator < 结束 |
| 69 | | |
| 70 | public static bool operator >(Box lhs, Box rhs) | // 重载 >:返回 bool(true 或 false) |
| 71 | { | // operator > 开始 |
| 72 | bool status = false; | // 先假设结果是 false |
| 73 | if (lhs.length > rhs.length && lhs.height | // 长更大、高也更大…… |
| 74 | > rhs.height && lhs.breadth > rhs.breadth) | // ……宽也更大,三项都更大才成立 |
| 75 | { | // if 开始 |
| 76 | status = true; | // 条件成立,结果改成 true |
| 77 | } | // if 结束 |
| 78 | return status; | // 返回比较结果 |
| 79 | } | // operator > 结束 |
| 80 | | |
| 81 | public static bool operator <=(Box lhs, Box rhs) | // 重载 <=:返回 bool(true 或 false) |
| 82 | { | // operator <= 开始 |
| 83 | bool status = false; | // 先假设结果是 false |
| 84 | if (lhs.length <= rhs.length && lhs.height | // 长、高都小于或等于…… |
| 85 | <= rhs.height && lhs.breadth <= rhs.breadth) | // ……宽也小于或等于,三项都满足才成立 |
| 86 | { | // if 开始 |
| 87 | status = true; | // 条件成立,结果改成 true |
| 88 | } | // if 结束 |
| 89 | return status; | // 返回比较结果 |
| 90 | } | // operator <= 结束 |
| 91 | | |
| 92 | public static bool operator >=(Box lhs, Box rhs) | // 重载 >=:返回 bool(true 或 false) |
| 93 | { | // operator >= 开始 |
| 94 | bool status = false; | // 先假设结果是 false |
| 95 | if (lhs.length >= rhs.length && lhs.height | // 长、高都大于或等于…… |
| 96 | >= rhs.height && lhs.breadth >= rhs.breadth) | // ……宽也大于或等于,三项都满足才成立 |
| 97 | { | // if 开始 |
| 98 | status = true; | // 条件成立,结果改成 true |
| 99 | } | // if 结束 |
| 100 | return status; | // 返回比较结果 |
| 101 | } | // operator >= 结束 |
| 102 | public override string ToString() | // override 是重写(上一节讲的),不是重载 |
| 103 | { | // ToString 开始 |
| 104 | return String.Format("({0}, {1}, {2})", length, breadth, height); | // 把长宽高拼成 (长, 宽, 高) 这样的文字 |
| 105 | } | // ToString 结束 |
| 106 | | |
| 107 | } | // Box 类结束 |
| 108 | | |
| 109 | class Tester | // 定义 Tester 类,放 Main |
| 110 | { | // Tester 类开始 |
| 111 | static void Main(string[] args) | // 程序入口 Main 方法 |
| 112 | { | // Main 开始 |
| 113 | Box Box1 = new Box(); // 声明 Box1,类型为 Box | // 创建第一个盒子 |
| 114 | Box Box2 = new Box(); // 声明 Box2,类型为 Box | // 创建第二个盒子 |
| 115 | Box Box3 = new Box(); // 声明 Box3,类型为 Box | // Box3 先随便 new 一个 |
| 116 | Box Box4 = new Box(); | // Box4 也先 new 一个,后面会改成指向 Box3 |
| 117 | double volume = 0.0; // 体积 | // 用来存体积 |
| 118 | | |
| 119 | // Box1 详述 | |
| 120 | Box1.setLength(6.0); | // Box1 的长 = 6 |
| 121 | Box1.setBreadth(7.0); | // Box1 的宽 = 7 |
| 122 | Box1.setHeight(5.0); | // Box1 的高 = 5 |
| 123 | | |
| 124 | // Box2 详述 | |
| 125 | Box2.setLength(12.0); | // Box2 的长 = 12 |
| 126 | Box2.setBreadth(13.0); | // Box2 的宽 = 13 |
| 127 | Box2.setHeight(10.0); | // Box2 的高 = 10 |
| 128 | | |
| 129 | // 使用重载的 ToString() 显示两个盒子 | |
| 130 | Console.WriteLine("Box1: {0}", Box1.ToString()); | // 输出 Box1: (6, 7, 5) |
| 131 | Console.WriteLine("Box2: {0}", Box2.ToString()); | // 输出 Box2: (12, 13, 10) |
| 132 | | |
| 133 | // Box1 的体积 | |
| 134 | volume = Box1.getVolume(); | // 6 × 7 × 5 = 210 |
| 135 | Console.WriteLine("Box1 的体积: {0}", volume); | // 输出 210 |
| 136 | | |
| 137 | // Box2 的体积 | |
| 138 | volume = Box2.getVolume(); | // 12 × 13 × 10 = 1560 |
| 139 | Console.WriteLine("Box2 的体积: {0}", volume); | // 输出 1560 |
| 140 | | |
| 141 | // 把两个对象相加 | |
| 142 | Box3 = Box1 + Box2; | // 调用 operator+:Box3 = (18, 20, 15) |
| 143 | Console.WriteLine("Box3: {0}", Box3.ToString()); | // 输出 Box3: (18, 20, 15) |
| 144 | // Box3 的体积 | |
| 145 | volume = Box3.getVolume(); | // 18 × 20 × 15 = 5400 |
| 146 | Console.WriteLine("Box3 的体积: {0}", volume); | // 输出 5400 |
| 147 | | |
| 148 | //comparing the boxes | |
| 149 | if (Box1 > Box2) | // 调用 operator >:6 > 12 不成立,结果 false |
| 150 | Console.WriteLine("Box1 大于 Box2"); | // 条件成立时输出这句(这次不走) |
| 151 | else | // 否则 |
| 152 | Console.WriteLine("Box1 不大于 Box2"); | // 输出 Box1 不大于 Box2 |
| 153 | if (Box1 < Box2) | // 调用 operator <:6 < 12、5 < 10、7 < 13 都成立,结果 true |
| 154 | Console.WriteLine("Box1 小于 Box2"); | // 输出 Box1 小于 Box2 |
| 155 | else | // 否则 |
| 156 | Console.WriteLine("Box1 不小于 Box2"); | // 条件不成立时输出这句(这次不走) |
| 157 | if (Box1 >= Box2) | // 调用 operator >=:三项都不满足,结果 false |
| 158 | Console.WriteLine("Box1 大于等于 Box2"); | // 条件成立时输出这句(这次不走) |
| 159 | else | // 否则 |
| 160 | Console.WriteLine("Box1 不大于等于 Box2"); | // 输出 Box1 不大于等于 Box2 |
| 161 | if (Box1 <= Box2) | // 调用 operator <=:三项都满足,结果 true |
| 162 | Console.WriteLine("Box1 小于等于 Box2"); | // 输出 Box1 小于等于 Box2 |
| 163 | else | // 否则 |
| 164 | Console.WriteLine("Box1 不小于等于 Box2"); | // 条件不成立时输出这句(这次不走) |
| 165 | if (Box1 != Box2) | // 调用 operator !=:长 6 和 12 就不等,结果 true |
| 166 | Console.WriteLine("Box1 不等于 Box2"); | // 输出 Box1 不等于 Box2 |
| 167 | else | // 否则 |
| 168 | Console.WriteLine("Box1 等于 Box2"); | // 条件不成立时输出这句(这次不走) |
| 169 | Box4 = Box3; | // Box4 改成指向 Box3 那个盒子:两个变量,同一个盒子 |
| 170 | if (Box3 == Box4) | // 调用 operator ==:同一个盒子,长宽高当然都相等,结果 true |
| 171 | Console.WriteLine("Box3 等于 Box4"); | // 输出 Box3 等于 Box4 |
| 172 | else | // 否则 |
| 173 | Console.WriteLine("Box3 不等于 Box4"); | // 条件不成立时输出这句(这次不走) |
| 174 | | |
| 175 | Console.ReadKey(); | // 等待按键(现在的 VS 不写也会停住) |
| 176 | } | // Main 结束 |
| 177 | } | // Tester 类结束 |
| 178 | } | // 命名空间结束 |
Box1: (6, 7, 5) Box2: (12, 13, 10) Box1 的体积: 210 Box2 的体积: 1560 Box3: (18, 20, 15) Box3 的体积: 5400 Box1 不大于 Box2 Box1 小于 Box2 Box1 不大于等于 Box2 Box1 小于等于 Box2 Box1 不等于 Box2 Box3 等于 Box4
编译时还有两条警告:
Program.cs(5,11): warning CS0660: “Box”定义运算符 == 或运算符 !=,但不重写 Object.Equals(object o) Program.cs(5,11): warning CS0661: “Box”定义运算符 == 或运算符 !=,但不重写 Object.GetHashCode()
重载了 == 和 !=,最好也重写 Equals(每个对象都有的“判断相等”方法)和 GetHashCode(算出对象的哈希码,给字典这类集合用,后面会讲),这样用 Equals 判断相等时,结果才和 == 一致。
7小结
- 运算符重载就是用
operator加符号,写一个public static的方法,告诉编译器自己写的类型遇到这个运算符该怎么算。 - 加号做什么全看方法里怎么写,Box 的加号加的是长宽高。
- 比较运算符要成对写;
&&、||不能直接重载。 - 重载了
+,+=自动能用,C# 14 起还能自己写。
下一节:如果好几个类都必须提供同样的方法,能不能像签合同一样,提前把这件事定下来?
