所有的运算符重载和类型转换重载都必须是公开,静态方法。
使用关键字operator作为方法名,因为这个位置原本是写方法名的,所以没有代码提示。
重载方法的返回值不一定必须是自己,但一定不能是void。不能在双方类型种定义相同的运算
运算符重载
运算符重载在operator后加上要重载运算符。参数类型至少有一个是自己类型。
一元运算(只有一个参数)
+和-
一元的+-运算一般是数字类型使用的。数字类型使用这些运算表示自己本身和自己的相反数
速度 a = new 速度();
速度 b = +a;
速度 c = -a;
class 速度
{
public int 米每秒;
public static 速度 operator +(速度 L) => new 速度 { 米每秒 = L.米每秒 };
public static 速度 operator -(速度 L) => new 速度 { 米每秒 = -L.米每秒 };
}
~和!
这两个运算符在逻辑运算中和位运算中计算所有比特完全相反的值。
class 速度
{
public int 米每秒;
public static bool operator !(速度 L) => L.米每秒 != 0;
public static int operator ~(速度 L) => -L.米每秒;
}
++和 – –
这两个运算符是数字类型使用的自增和自减。重载的返回值必须是自己或自己的派生。
和数字的自增自减一样,如果写在前面,那么返回计算后的值。
如果写在后面,那么返回还没计算的值。无论哪种方式,计算完毕后的值都会替换原始值。
速度 s = new 速度();
var a = s;
var b = s++;
var c = ++s;
Console.WriteLine(s == a);//False
Console.WriteLine(s == b);//False
Console.WriteLine(a == b);//True
Console.WriteLine(s == c);//True
class 速度
{
public int 米每秒;
public static 速度 operator ++(速度 L) => new 速度 { 米每秒 = L.米每秒 + 1 };
public static 速度 operator --(速度 L) => new 速度 { 米每秒 = L.米每秒 - 1 };
}
true和false
true和false是配对的运算,必须成对重载。且必须返回bool类型。
重载了true后,这个类型可以直接当作流程控制语句和三元运算符的条件。
false重载几乎没什么用。
灵能风暴 a = new 灵能风暴();
if (a) { }
var b = a ? 1 : 2;
//bool c = a;重载true不意味着可以直接转换为bool类型。
//if (!a) { }重载true只能把自己当条件,!a的结果由!运算符重载。
class 灵能风暴
{
public int 持续时间 { get; protected set; }
public object[] 影响目标 { get; protected set; }
public int 每秒伤害 { get; protected set; }
public static bool operator true(灵能风暴 L) => L is { 持续时间: > 0, 影响目标.Length: > 0 };
public static bool operator false(灵能风暴 L) => L is not { 持续时间: > 0, 影响目标.Length: > 0 };
}
这两种重载的结果不需要互补。即一方结果为true时,另一方结果可以也是true。
二元运算(有两个参数)
+和 -
计算两个类型相加或相减的结果。
不是所有类型都满足交换律,有些计算必须某种类型在左边。希望两种顺序都能计算就需要重载两个方法。
如果双方都写了相同的定义,那么在进行运算时会无法判断使用哪个类里面的方法。
class 时间段
{
public int 年, 月, 日;
public static 时刻 operator +(时间段 L, 时刻 R)
=> new 时刻() { 年 = L.年 + R.年, 月 = L.月 + R.月, 日 = L.日 + R.日 };
}
class 时刻
{
public int 年, 月, 日;
public static 时刻 operator +(时刻 L, 时间段 R)
=> new 时刻() { 年 = L.年 + R.年, 月 = L.月 + R.月, 日 = L.日 + R.日 };
public static 时刻 operator -(时刻 L, 时间段 R)
=> new 时刻() { 年 = L.年 - R.年, 月 = L.月 - R.月, 日 = L.日 - R.日 };
}
*和 / 和%
这个懒得写示例了。
&和 | 和^
这个懒得写示例了。
>>和<<
位运算符。返回类型不限,但左边参数必须是自身类型,右边参数必须是int类型。
>和<
必须成对重载。返回类型必须是bool类型。不需要互补。
>=和<=
必须成对重载。返回类型必须是bool类型。不需要互补。
!=和==
必须成对重载。返回类型必须是bool类型。不需要互补。
自动重载的运算
复合运算
如果二元运算的返回类型是自己,那么对应的复合运算也会一起重载。
速度 a = new 速度();
a += a;
class 速度
{
public int 米每秒;
public static 速度 operator +(速度 L, 速度 R)
=> new 速度() { 米每秒 = L.米每秒 + R.米每秒 };
public static 速度 operator -(速度 L, 速度 R)
=> new 速度() { 米每秒 = L.米每秒 - R.米每秒 };
}
逻辑运算
如果重载了&或 | ,且返回类型为自己,且重载了 true 和false。
那么会自动重载&&和 || 。
示例 a = new 示例() { b = false };
示例 b = new 示例() { b = true };
var c = a && b;
var d = a || b;
var e = b && a;
var f = b || a;
Console.WriteLine(a == c); //True
Console.WriteLine(a == d); //False
Console.WriteLine(b == e); //False
Console.WriteLine(b == f); //True
class 示例
{
public bool b;
public static 示例 operator &(示例 L, 示例 R) => new 示例();
public static 示例 operator |(示例 L, 示例 R) => new 示例();
public static bool operator true(示例 L) => L.b;
public static bool operator false(示例 L) => !L.b;
}
如果&&左侧值重载的false运算结果为bool值true,那么不会执行&运算直接返回左侧值。
如果 || 左侧值重载的true运算结果为bool值true,那么不会执行 | 运算直接返回左侧值。
否则,计算&或 | 的运算。