用户定义的类型可重载预定义的 C# 运算符。也就是说,当一个或两个操作数都是某类型时,此类型可提供操作的自定义实现。“可重载运算符”部分介绍了哪些 C# 运算符可重载。
使用 operator 关键字来声明运算符。运算符声明必须符合以下规则:
- 同时包含 public 和 static 修饰符
- 一元运算符有一个输入参数。二元运算符有两个输入参数。在每种情况下,都至少有一个参数必须具有类型 T 或 T?,其中 T 是包含运算符声明的类型;T? 表明允许该类型为 null 值。
下面的示例定义了一个表示分数的简单结构。该结构会重载一些算术运算符:
static void Main(string[] args)
{
JG分数 a = new ( 5 , 4 );
JG分数 b = new ( 1 , 2 );
Console . WriteLine ( $"-a = {-a}" );
Console . WriteLine ( $"a + b = {a + b}" );
Console . WriteLine ( $"a - b = {a - b}" );
Console . WriteLine ( $"a × b = {a * b}" );
Console . WriteLine ( $"a ÷ b = {a / b}" );
}
public readonly struct JG分数
{
private readonly int Zi , Mu;
public JG分数 ( int 分子 , int 分母 )
{
if ( 分母 == 0 )
{
throw new ArgumentException ( "分母不能是 0。" , nameof ( 分母 ) );
}
Zi = 分子;
Mu = 分母;
}
public static JG分数 operator + ( JG分数 自身 ) => 自身;
public static JG分数 operator - ( JG分数 自身 ) => new ( -(自身 . Zi) , 自身 . Mu );
public static JG分数 operator + ( JG分数 加数1 , JG分数 加数2 ) => new ( 加数1 . Zi * 加数2 . Mu + 加数2 . Zi * 加数1 . Mu , 加数1 . Mu * 加数2 . Mu );
public static JG分数 operator + ( JG分数 加数1 , int 加数2 ) => new ( 加数1 . Zi + 加数2 * 加数1 . Mu , 加数1 . Mu );
public static JG分数 operator - ( JG分数 被减数 , JG分数 减数 ) => 被减数 + ( -减数 );
public static JG分数 operator * ( JG分数 乘数1 , JG分数 乘数2 ) => new ( 乘数1 . Zi * 乘数2 . Zi , 乘数1 . Mu * 乘数2 . Mu );
public static JG分数 operator / ( JG分数 被除数 , JG分数 除数 )
{
if ( 除数 . Zi == 0 )
throw new DivideByZeroException ( "除数不能为 0。" );
return new ( 被除数 . Zi * 除数 . Mu , 被除数 . Mu * 除数 . Zi );
}
public override string ToString ( )
{
JG分数 f = FF约分 ( this );
return $"{f . Zi} / {f . Mu} = {( double ) f . Zi / ( double ) f . Mu}";
}
private JG分数 FF约分 ( JG分数 分数 )
{
int 分子 = 分数 . Zi;
int 分母 = 分数 . Mu;
BigInteger zi = new ( 分子 ) , mu = new ( 分母 );
BigInteger gys = BigInteger . GreatestCommonDivisor (mu, zi );
zi /= gys;
mu /= gys;
return new ( ( int ) zi , ( int ) mu );
}
}
可以通过定义从 int 到 JG分数 的隐式转换来扩展前面的示例。然后,重载运算符将支持这两种类型的参数。也就是说,可以将一个整数添加到一个分数中,得到一个分数结果。
上例来自 MSDN,我多写了一个关于分数加整数和约分的过程。约分的过程中,使用了 BigInteger 的求最大公约数的过程(GreatestCommonDivisor),以便约分分数。
还可以使用 operator 关键字来定义自定义类型转换。
可重载运算符
运算符 | 说明 |
---|---|
+x, -x, !x, ~x, ++, --, true, false | true 和 false 必须成对重载 |
x + y, x - y, x * y, x / y, x % y, x & y, x or y, x ^ y, x << y, x >> y, x >>> y | |
x == y, x != y, x < y, x > y, x <= y, x >= y | == 和 !=、< 和 >、<= 和 >= 必须成对重载 |
备注: 第二行中的 x or y 实际是 x | y。
不可重载运算符
运算符 | 备选方法 |
---|---|
x && y,x 短路or y | 重载 true 和 false 运算符以及 & 或 or 运算符 |
a[i],a?[i] | 定义索引器 |
(T)x | 定义可由强制转换表达式执行的自定义类型转换 |
+=,-=,*=,/=,%=,&=,or=,^=,<<=,>>=,>>>= | 重载相应的二元运算符。例如,重载二元 + 运算符时,会隐式重载 += |
^x,x = y,x.y,x?.y,c ? t : f,x ?? y,??= y,x..y,x->y,=>,f(x),as,await,checked,unchecked,default,delegate,is,nameof,new,sizeof,stackalloc,switch,typeof,with | 无 |
备注: 第一行中的“短路or”实际为“||”,“or”实际为“|”。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。