C# 之 常见和不常见的运算符汇总
C# 提供了许多运算符。 其中许多都受到内置类型的支持,可用于对这些类型的值执行基本操作。
一,算术运算符
算术运算符:
- 一元: ++(增量)、–(减量)、+(加)和 -(减)运算符
- 二元 :*(乘法)、/(除法)、%(余数)、+(加法)和 -(减法)运算符
算术运算符是非常简单和常用的运算符,直接看代码吧;
using System;
namespace CsharpOp
{ class Program { static void Main(string[] args) { Console.WriteLine("C# -- 算数运算符"); int num = 1; // 前缀增量 先计算后执行... Console.WriteLine(++num); //输出: 2 Console.WriteLine(num); //输出: 2 Console.WriteLine(--num); //输出: 1 Console.WriteLine(num); //输出: 1 Console.WriteLine("---------------"); // 后缀增量 先执行后计算... Console.WriteLine(num++); //输出: 1 Console.WriteLine(num); //输出: 2 Console.WriteLine(num--); //输出: 2 Console.WriteLine(num); //输出: 1 Console.WriteLine("---------------"); int x = 3, y = 4; // 加,减,乘,除,取模 运算 Console.WriteLine(x + y); //输出: 7 Console.WriteLine(x - y); //输出: -1 Console.WriteLine(x * y); //输出: 12 Console.WriteLine(x / y); //输出: 0 Console.WriteLine(x % y); //输出: 3 Console.ReadKey(); } }
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
运算符优先级和关联性
优先级由高到低的顺序排序:
- 后缀增量 x++ 和减量 x-- 运算符
- 前缀增量 ++x 和减量 --x 以及一元 + 和 - 运算符
- 乘法 *、/ 和 % 运算符
- 加法 + 和 - 运算符
二元算数运算符是左结合运算符。 也就是说,具有相同优先级的运算符按从左至右的顺序计算。
二,逻辑运算符
逻辑运算:
- 一元 !(逻辑非)运算符。
我一般叫它为取反运算符,即计算结果为false,它是true,计算结果为true时它为true。
bool bo = true;
Console.WriteLine(!bo); //输出: False
Console.WriteLine(!(3 == 4)); //输出: True
- 1
- 2
- 3
-
二元 &(逻辑与)、|(逻辑或)和 ^(逻辑异或)运算符。 这些运算符始终计算两个操作数。
- & :运算符计算操作数的逻辑与。 如果 x 和 y 的计算结果都为 true,则 x & y 的结果为 true。 否则,结果为 false。
- | 运算符计算操作数的逻辑或。 如果 x 或 y 的计算结果为 true,则 x | y 的结果为 true。 否则,结果为 false。
- ^ 运算符计算操作数的逻辑异或(亦称为“逻辑 XOR”)。 对于 bool 操作数,^ 运算符的计算结果与不等运算符 != 相同,也就是说当X和Y同为true或false时,x^y 结果为 false;当X和Y不相同时,则其结果为true。
// & 与运算 Console.WriteLine(true & true); //输出: True Console.WriteLine(true & false); //输出: False Console.WriteLine(false & true); //输出: True Console.WriteLine(false & false); //输出: False // | 或运算 Console.WriteLine(true | true); //输出: True Console.WriteLine(true | false); //输出: True Console.WriteLine(false | true); //输出: True Console.WriteLine(false | false); //输出: False // ^ 亦或运算 Console.WriteLine(true ^ true); //输出: False Console.WriteLine(true ^ false); //输出: True Console.WriteLine(false ^ true); //输出: True Console.WriteLine(false ^ false); //输出: False
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 二元 &&(条件逻辑与)和 ||(条件逻辑或)运算符。 这些运算符仅在必要时才计算右侧操作数。
- &&:也叫短路与,计算结果和 & 的执行结果一致。当x,y都为true时,结果为true,反之,结果为false;当x(左侧结果)为false时,不会计算y,直接得到结果false。
- ||:也叫短路,计算结果和 | 的执行结果一致。当x,y有一个为true时,结果为true,反之,结果为false;当x(左侧结果)为true时,不会计算y,直接得到结果true。
逻辑运算符优先级
按优先级从高到低的顺序排序:
- 逻辑非运算符 !
- 逻辑与运算符 &
- 逻辑异或运算符 ^
- 逻辑或运算符 |
- 条件逻辑与运算符 &&
- 条件逻辑或运算符 ||
三,按位和移位运算符
- 一元 ~(按位求补)运算符:即二进制下0和1的相互变换;
4的二进制是:00000100
则按位求补 : 11111011
byte a = 4; // 4的二进制: 00000100
byte b = (byte)~a;
Console.WriteLine(a); // 输出: 4
Console.WriteLine(b); // 输出: 251
Console.WriteLine(Convert.ToString(a, toBase: 2));// 输出: 100
Console.WriteLine(Convert.ToString(b, toBase: 2));// 输出: 11111011
- 1
- 2
- 3
- 4
- 5
- 6
-
二进制 <<(向左移位)和 >>(向右移位)移位运算符;
向左移位举例:
4的二进制是 :00000100
4左移两位是 :000100__ (下划线两位用0补位)
左移两位结果:00010000
向右移位同理
4的二进制是 :00000100
4右移两位是 :000000100(多出来的直接舍弃)
右移两位结果:00000001上面描述了二进制计算,那么对于十进制来说,左移几位就是乘以2的几次幂。(左移一位:2,两位:22,三位222);同理可知,右移时就是除以2的几次幂。
因为位移比乘除速度快,对效率要求高,而且满足 2 的幂次方的乘除运方,可以采用位移的方式进行。
// 左移两位
byte a = 4; // 4的二进制: 00000100
byte b = (byte)(a << 2);
Console.WriteLine(a); // 输出: 4
Console.WriteLine(b); // 输出: 16
Console.WriteLine(Convert.ToString(a, toBase: 2));// 输出: 100
Console.WriteLine(Convert.ToString(b, toBase: 2));// 输出: 10000 // 右移两位
byte c = 4; // 4的二进制: 00000100
byte d = (byte)(a >> 2);
Console.WriteLine(c); // 输出: 4
Console.WriteLine(d); // 输出: 1
Console.WriteLine(Convert.ToString(c, toBase: 2));// 输出: 100
Console.WriteLine(Convert.ToString(d, toBase: 2));// 输出: 1
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
-
二进制 &(逻辑 AND)、|(逻辑 OR)和 ^(逻辑异或)运算符
-
&:与运算,从第一个非0位开始计算,对应位两个都是1则结果为1,否则结果为0。举例:
4: 00000100
5: 00000101
---------------------
4: 00000100 -
|:或运算,从第一个非0位开始计算,对应位有一个是1则结果为1,否则结果为0。举例:
4: 00000100
5: 00000101
---------------------
5: 00000101 -
^:亦或运算,从第一个非0位开始计算,对应位两个不同则结果为1,否则结果为0。举例:
4: 00000100
5: 00000101
---------------------
1: 00000001
-
byte x = 4; // 4的二进制: 00000100 byte y = 5; // 5的二进制: 00000101 // & 与运算 byte z = (byte)(x & y); Console.WriteLine(z); // 输出: 4 Console.WriteLine(Convert.ToString(z, toBase: 2));// 输出: 100 // | 或运算 z = (byte)(x | y); Console.WriteLine(c); // 输出: 5 Console.WriteLine(Convert.ToString(z, toBase: 2));// 输出: 101 // ^ 亦或运算 z = (byte)(x ^ y); Console.WriteLine(c); // 输出: 5 Console.WriteLine(Convert.ToString(z, toBase: 2));// 输出: 1
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
四,关系运算符
- ==(等于)、!=(不等于)、 <(小于)、>(大于)、<=(小于或等于)和 >=(大于或等于)关系运算符比较其操作数。
char 类型支持关系运算符。 在使用 char 操作数时,将比较对应的字符代码。
枚举类型也支持比较运算符。 对于相同枚举类型的操作数,基础整数类型的相应值会进行比较。
运算符可重载性:
用户定义类型可以重载 ==、!=、<、>、<= 和 >= 运算符。
如果某类型重载/ == 或 !=运算符之一,它必须同时重载 /== 和!=。
如果某类型重载 < 或 > 运算符之一,它必须同时重载 < 和 >。
如果某类型重载 <= 或 >= 运算符之一,它必须同时重载 <= 和 >=。
五,成员访问运算符
访问类型成员时,可以使用以下运算符和表达式:
- .(成员访问):用于访问命名空间或类型的成员
double pai = System.Math.PI;
- 1
- [](数组元素或索引器访问):用于访问数组元素或类型索引器
int[] arr = new int[3] { 1, 2, 3 };
Console.WriteLine(arr[1]); // 输出: 2
- 1
- 2
- ?. 和 ?[](null 条件运算符):仅当操作数为非 null 时才用于执行成员或元素访问运算
以?[]访问为例:
var arr = new List<int[]>() { new int[] { 1, 2, 3 }, null };
Console.WriteLine(arr[0][1]); // 输出: 2
Console.WriteLine(arr?[0][1]); // 输出: 2 Console.WriteLine(arr[1]); // 输出:
Console.WriteLine(arr?[1]?[0]); // 输出:
//Console.WriteLine(arr?[1][0]); // 报错: System.NullReferenceException
// 等价于
if (arr != null)
{ Console.WriteLine(arr[1]); if (arr[1] != null) { Console.WriteLine(arr[1][0]); }
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
在这里可以理解为:问号再谁后面就判断谁是否为null,为null则不执行后面操作。
- ^(从末尾开始索引):指示元素位置来自序列的末尾。
a[^几]就是倒数第几个的意思,使用时主要下别越界了。
int[] array = new int[5] { 1, 2, 3, 4, 5 };
Console.WriteLine(array[1]); // 输出: 2
Console.WriteLine(array[^1]); // 输出: 5
//Console.WriteLine(array[^0]); // 报错:数组索引越界,System.IndexOutOfRangeException
- 1
- 2
- 3
- 4
- . .(范围):指定可用于获取一系列序列元素的索引范围;
写法为[startIndex. .endIndex) --> [开始索引. .结束索引) 是一个左闭右开区间;若开始索引不写,则默认0开始;若结束索引不写,则默认取到数组结束;若都不写,则就是整个数组。
动态写法(. . ^):范围结束还可以这样定义,[startIndex. .^Index)–> 解释为从第startIndex个元素索引开始 到 倒数第Index个元素结束。
int[] array = new int[5] { 1, 2, 3, 4, 5 };
Console.WriteLine();
for (int i = 0; i < array[1..3].Length; i++)
{ Console.Write(array[1..3][i] + " "); //输出2 3
}
Console.WriteLine();
// 开始索引不写,默认从0索引开始
for (int i = 0; i < array[..3].Length; i++)
{ Console.Write(array[..3][i] + " "); //输出2 3 4
}
Console.WriteLine();
// 结束索引不写,默认到数组长度结束
for (int i = 0; i < array[1..].Length; i++)
{ Console.Write(array[1..][i] + " "); //输出2 3 4 5
}
Console.WriteLine();
// 从1索引到倒数第二个元素的索引的区间。
int[] indexArr = array[1..^2];
for (int i = 0; i < indexArr.Length; i++)
{ Console.Write(indexArr[i] + " "); //输出2 3
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
六,类型测试运算符
- is 运算符:用于检查表达式的运行时类型是否与给定类型兼容
X is Y: 若X可以通过引用转换,装箱,拆箱来转换为类型Y,则X is Y返回True,否则,则返回False;is 运算符不会考虑用户定义的转换。
// 基类 public class BaseClass { }
// 派生类 public class DerivedClass : BaseClass { } class Program { static void Main(string[] args) { var b = new BaseClass(); Console.WriteLine(b is BaseClass); // 输出: True Console.WriteLine(b is DerivedClass); // 输出: False var d = new DerivedClass(); Console.WriteLine(d is BaseClass); // 输出: True Console.WriteLine(d is DerivedClass); // 输出: True Console.ReadKey(); } }
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- as 运算符:用于将表达式显式转换为给定类型(如果其运行时类型与该类型兼容)。 如果无法进行转换,则 as 运算符返回 null。 与强制转换表达式 不同,as 运算符永远不会引发异常。
// 基类
public class BaseClass { }
// 派生类 public class DerivedClass : BaseClass { } class Program { static void Main(string[] args) { BaseClass b = new BaseClass(); // as DerivedClass d = b as DerivedClass; // 强制转换 DerivedClass d1 = (DerivedClass) b; Console.ReadKey(); } }
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 运算符:用于获取某个类型的 System.Type 实例
// 基类
public class BaseClass { }
// 派生类 public class DerivedClass : BaseClass { } class Program { static void Main(string[] args) { var d = new DerivedClass(); Console.WriteLine(d is BaseClass); // 输出: True Console.WriteLine(d.GetType() == typeof(BaseClass)); // 输出: True Console.WriteLine(d is DerivedClass); // 输出: True Console.WriteLine(d.GetType() == typeof(DerivedClass)); // 输出: True Console.ReadKey(); } }
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
七,?? 和 ??= 运算符
- 如果左操作数的值不为 null,则 null 合并运算符 ?? 返回该值;否则,它会计算右操作数并返回其结果。 如果左操作数的计算结果为非 null,则 ?? 运算符不会计算其右操作数。
??举例:
int? a = null;
int b = a ?? -1;
Console.WriteLine(b); // output: -1 // 等价于 三目运算符
b = (a == null ? (int)a : -1);
// 等价于 if else
if (a == null) b = -1;
else b = (int)a;
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
??=举例:变量!=null,则被表达式赋值
variable ??= expression;
//等价于
if (variable is null)
{ variable = expression;
}
- 1
- 2
- 3
- 4
- 5
- 6
文章来源: czhenya.blog.csdn.net,作者:陈言必行,版权归原作者所有,如需转载,请联系作者。
原文链接:czhenya.blog.csdn.net/article/details/109230462
- 点赞
- 收藏
- 关注作者
评论(0)