【C#基础】C# 运算符总结
序号 | 系列文章 |
---|---|
2 | 【C#基础】C# 基础语法解析 |
3 | 【C#基础】C# 数据类型总结 |
4 | 【C#基础】C# 变量和常量的使用 |
文章目录
- 前言
- 运算符
- 1,算术运算符
- 2,布尔逻辑运算符
- 3,位运算符
- 4,关系运算符
- 5,赋值运算符
- 6,其他运算符
- 7,运算符的优先级
- 8,运算符重载
- 结语
前言
😄大家好,我是writer桑,前面一章已经学习了 C# 中变量和常量的使用,那本章就开始学习 C# 程序中的运算符概念,希望看完大家能够有所收获,感谢支持!
运算符
运算符是一种告诉编译器执行特定行为的数学或逻辑操作的符号。C# 内置了许多类型的运算符,用于对这些类型的值执行一些基本的操作。这些运算符包括:算术运算符、比较运算符、布尔逻辑运算符、位运算符和相等运算符。
1,算术运算符
以下表格展示了一元运算符,其中假设变量 a 等于10:
一元运算符 | 描述 | 实例 |
---|---|---|
++ | 增量运算符 | ++a 输出 11 |
-- | 减量运算符 | --a 输出 9 |
+ | 一元加运算符 | +a 输出 10 |
- | 一元减运算符 | -a 输出 -10 |
1.1,增量和减量运算符:
增量运算符 ++ 按 1 递增起操作数。操作数必须是变量、属性访问或索引器访问。其中增量运算符以两种形式进行支持: 前缀增量运算符 ++x 表示先递增再赋值和后缀增量运算符 x++ 表示先赋值再递增; 而减量运算符和增量运算符很类似,只不过是 + 号换成 - 号,把增量换成减量,主要的作用都是一样的。 这里借增量运算符来讨论。
示例如下:
int a = 10;
int b = 10;// 后缀增量运算符
Console.WriteLine(a++); // 输出 10
Console.WriteLine(a); // 输出 11
// 前缀增量运算符
Console.WriteLine(++b); // 输出 11int c = 10;
int d = 10;// 后缀减量运算符
Console.WriteLine(c--); // 输出 10
Console.WriteLine(c); // 输出 9
// 前缀减量运算符
Console.WriteLine(--d); // 输出 9
1.2,一元加和减运算符:
一元 + 运算符表示对其操作数取正,也就是返回其操作数的值,一元 - 运算符对其操作数取负,也就是返回其操作数的负值。
示例如下:
Console.WriteLine(+4); // 输出 4
Console.WriteLine(-4); // 输出 -4
Console.WriteLine(-(-4)); // 输出 4
uint a = 5;
var b = -a;Console.WriteLine(b); // 输出 -5
Console.WriteLine(b.GetType()); // 输出 System.Int64
Console.WriteLine(-double.NaN); // 输出 NaN
以下表格展示了二元运算符,其中假设变量 a 等于10,变量 b 等于 20:
二元运算符 | 描述 | 实例 |
---|---|---|
* | 乘法运算符 | a * b 输出 200 |
/ | 除法运算符 | b / a 输出 2 |
% | 余数运算符 | b % a 输出 0 |
+ | 加法运算符 | b + a 输出 30 |
- | 减法运算符 | b - a 输出 10 |
1.3,乘法运算符:
乘法运算符 * 表示计算其操作数的乘积,在不安全的上下文中, 一元 * 运算符还可以表示指针间接运算符。
示例如下:
Console.WriteLine(5 * 2); // 输出 10
Console.WriteLine(0.5 * 2.5); // 输出 1.25
Console.WriteLine(0.1m * 23.4m); // 输出 2.34
// 不安全的上下文
unsafe
{char letter = 'A';char* pointerToLetter = &letter;Console.WriteLine(pointerToLetter);Console.WriteLine($"Value of the `letter` variable: {letter}");Console.WriteLine($"Address of the `letter` variable:{ (long)pointerToLetter:X}");
}
1.4,除法运算符:
除法运算符 / 表示计算其操作数之间相除的商,整数类型的操作数,/ 运算符的结果为整数类型,并且等于两个操作数之商项向零舍入后的结果;若想要商的结果为浮点数形式,则需要使用浮点类型的操作数。
示例如下:
Console.WriteLine(13 / 5); // 输出 2
Console.WriteLine(-13 / 5); // 输出 -2
Console.WriteLine(13 / -5); // 输出 -2
Console.WriteLine(-13 / -5); // 输出 2
// 浮点数形式
Console.WriteLine(13 / 5.0); // 输出 2.6int a = 13;
int b = 5;
Console.WriteLine((double)a / b); // 输出 2.6
1.5,余数运算符:
余数运算符 % 表示计算左侧操作数除以右侧操作数后的余数。 整数类型的操作数,a % b 的结果是 a - (a / b) * b 得出的值。 非零余数的符号与左侧操作数的符号相同。
示例如下:
Console.WriteLine(5 % 4); // 输出 1
Console.WriteLine(5 % -4); // 输出 1
Console.WriteLine(-5 % 4); // 输出 -1
Console.WriteLine(-5 % -4); // 输出 -1
1.6,加法运算符:
加法运算符 + 表示计算操作数之间的和,同时 + 运算符还可以用于字符串串联和委托组合。
示例如下:
Console.WriteLine(5 + 4); // 输出 9
Console.WriteLine(5 + 4.3); // 输出 9.3
Console.WriteLine(5.1m + 4.2m); // 输出 9.3
// 字符串串联
Console.WriteLine("Hello" + "World"); // Hello World
// 委托组合
Action a = () => Console.Write("a");
Action b = () => Console.Write("b");
Action ab = a + b;
ab(); // 输出:ab
1.7,减法运算符:
减法运算符 - 表示从其左侧操作数中减去其右侧操作数,同时 - 运算符还可以删除委托。
示例如下:
Console.WriteLine(47 - 3); // 输出 44
Console.WriteLine(5 - 4.3); // 输出 0.7
Console.WriteLine(7.5m - 2.3m); // 输出 5.2
// 删除委托
Action a = () => Console.Write("a");
Action b = () => Console.Write("b");
Action ab = a + b - b;
ab(); // 输出:a
2,布尔逻辑运算符
以下表格展示了布尔逻辑运算符,其中假设变量 a 为 true,变量 b 为 false:
布尔运算符 | 描述 | 实例 |
---|---|---|
! | 逻辑非运算符 | !a 为 False |
& | 逻辑与运算符 | a & b 为 False |
| | 逻辑或运算符 | a | b 为 True |
^ | 逻辑异或运算符 | a ^ b 为 True |
&& | 条件逻辑与运算符 | a && b 为 False |
|| | 条件逻辑或运算符 | a || b 为 True |
2.1,逻辑非运算符:
一元前缀运算符 ! 表示计算操作数的逻辑非。也就是说,如果操作数的计算结果为false,它生成true,相对的如果操作数的计算结果为 true,它生成 false;同时一元后缀运算符 !表示 null 包容运算符或 null 抑制运算符,可以在已启用的可为空的注释上下文中,来取消上述表达式的所有可为 null 警告。
示例如下:
bool passed = false;
Console.WriteLine(!passed); // 输出:True
Console.WriteLine(!true); // 输出:False
public static void Main()
{Person? p = Find("John");if (IsValid(p)){Console.WriteLine($"Found {p!.Name}");}
}public static bool IsValid(Person? person)=> person is not null && person.Name is not null;// 如果肯定某个表达式不能为 null,但编译器无法识别它,
// 可以使用 null 包容运算符。在此示例中,如果 IsValid 方法返回 true,
// 则其参数不是 null,可以放心取消对它的引用。
2.2,逻辑与运算符:
逻辑与运算符 & 表示计算操作数的逻辑与。 只有当 x 和 y 的计算结果都为 true,则 x & y 的输出结果才为 true。 否则,其它结果全为 false。 注意即使左侧操作数计算结果为 false,& 运算符也会计算这两个操作数;对于整型数值类型的操作数,& 运算符计算其操作数的位逻辑 AND;一元 & 运算符会返回其操作数的地址。
示例如下:
// 逻辑非运算
Console.WriteLine(true & true); // 输出:True
Console.WriteLine(false & true); // 输出: False
// 位逻辑 AND 运算
Console.WriteLine(1 & 0); // 输出:0
// 不安全的上下文
unsafe
{// 一元 & 运算符返回其操作数的地址int number = 27;int* pointerToNumber = &number;Console.WriteLine($"变量值: {number}");Console.WriteLine($"变量地址: {(long)pointerToNumber:X}");
}
2.3,逻辑或运算符:
逻辑或运算符 | 表示计算操作数的逻辑或。如果 x 或 y 的计算结果为 true,则 x | y 的结果为 true,否则,其它结果全为false。即使左侧操作数计算结果为 true,| 运算符也会计算这两个操作数;对于整型数值类型的操作数,| 运算符会计算其操作数的位逻辑 OR。
示例如下:
// 逻辑或运算
Console.WriteLine(true | false); // 输出:True
Console.WriteLine(false & false); // 输出: False
// 位逻辑 OR 运算
Console.WriteLine(1 & 0); // 输出 0
2.4,逻辑异或运算符:
逻辑异或运算符 ^ 表示计算操作数的逻辑异或(亦称为“逻辑 XOR”)。当 x 的布尔值和 y 的布尔值不相等时,那么 x ^ y 的结果为 true。 否则,其它结果全为 false。 也就是说,对于 bool 操作数,^ 运算符的计算结果与不等运算符 != 相同;同时对于整型数值类型的操作数,^ 运算符计算其操作数的位逻辑异或。
示例如下:
// 逻辑异或运算
Console.WriteLine(true ^ false);
Console.WriteLine(true ^ true);
Console.WriteLine(false ^ false);
// 位逻辑异或运算
Console.WriteLine(1 ^ 0); // 输出: 1
2.5,条件逻辑与运算符:
条件逻辑与运算符 &&(亦称为“短路”逻辑与运算符)表示计算操作数的逻辑与。 如果 x 和 y 的计算结果都为 true,则 x && y 的结果为 true, 否则,其它结果都为 false;和逻辑与运算符 & 不同的是如果 && 运算符左侧操作数 x 的计算结果为 false,那么就不执行右侧操作数 y 的计算结果。
示例如下:
using System;public class Program
{static bool SecondOperand(){Console.WriteLine("对第二个操作数求值。");return true;}static void Main(){bool a = false && SecondOperand(); // 左侧为false, 不会执行 SecondOperand 方法的操作 Console.WriteLine(a); // 输出:Falsebool b = true && SecondOperand(); // 输出:对第二个操作数求值。 Console.WriteLine(b); // True } }
2.6,条件逻辑或运算符:
条件逻辑或运算符 ||(亦称为“短路”逻辑或运算符)表示计算操作数的逻辑或。 如果 x 或 y 的计算结果为 true,则 x || y 的结果为 true。 否则,其它结果都为 false;和逻辑或运算符 | 不同的是如果 || 运算符左侧操作数 x 的计算结果为 true,则不执行右侧操作数 y 的计算结果。
示例如下:
using System;public class Program
{static bool SecondOperand(){Console.WriteLine("对第二个操作数求值。");return false;}static void Main(){bool a = true || SecondOperand(); // 左侧为true, 不会执行 SecondOperand 方法的操作 Console.WriteLine(a); // 输出:Truebool b = false || SecondOperand(); // 输出:对第二个操作数求值。 Console.WriteLine(b); // 输出:false}}
3,位运算符
以下表格展示了位运算符和移位运算符,其中假设变量 a 为 1,变量 b 为 2:
位运算符 | 描述 | 实例 |
---|---|---|
~ | 按位求补运算符 | ~a 等于 -2 |
<< | 左移位运算符 | a << 2 等于 4 |
>> | 右移位运算符 | a >> 2 等于 0 |
>>> | 无符号右移运算符 | a >>> 2 等于 0 |
& | 逻辑与运算符 | a & b 等于 0 |
^ | 逻辑异或运算符 | a ^ b 等于 3 |
| | 逻辑或运算符 | a | b 等于 3 |
3.1,按位求补运算符:
~ 运算符表示通过反转每个位产生其操作数的按位求补; 同时也可以使用 ~ 符号来声明终结器(也就是折构函数)。
示例如下:
uint a = 0b_0000_1111_0000_1111_0000_1111_0000_1100;
uint b = ~a; Console.WriteLine(Convert.ToString(b, toBase: 2)); // 输出: 11110000111100001111000011110011
// 终结器的简单实例
class Car
{~Car() {// 清理语句....}
}
3.2,左移位运算符:
<< 运算符表示将其左侧操作数向左移动右侧操作数定义的位数。 有关右侧操作数如何定义移位计数的信息,同时左移运算放弃超出结果类型范围的高阶位,并将低阶空位位置设置为零,也就是高位舍弃,低位补零。
示例如下:
uint x = 0b_1100_1001_0000_0000_0000_0000_0001_0001;
Console.WriteLine($"之前: {Convert.ToString(x, toBase: 2)}");uint y = x << 4;
Console.WriteLine($"之后: {Convert.ToString(y, toBase: 2)}");// 输出:
// 之前: 11001001000000000000000000010001
// 之后: 10010000000000000000000100010000
3.3,右移位运算符:
>> 运算符表示将其左侧操作数向右移动右侧操作数定义的位数,右移位运算会放弃低阶位。而高顺序空位位置是根据左侧操作数类型设置的:当左侧操作数的类型是 int 或 long 时,如果左侧操作数为非负,高顺序空位位置设置为0, 如果为负, 则将该位置设置为1; 当左侧操作数的类型是 uint 或 ulong时,则高顺序空位位置始终设置为0。
示例如下:
// int类型
int a = int.MinValue;
Console.WriteLine($"之前: {Convert.ToString(a, toBase: 2)}");int b = a >> 3;
Console.WriteLine($"之后: {Convert.ToString(b, toBase: 2)}");
// 输出:
// 之前: 10000000000000000000000000000000
// 之后: 11110000000000000000000000000000
// uint 类型
uint c = 0b_1000_0000_0000_0000_0000_0000_0000_0000;
Console.WriteLine($"之前: {Convert.ToString(c, toBase: 2),32}");uint d = c >> 3;
Console.WriteLine($"之后: {Convert.ToString(d, toBase: 2).PadLeft(32,
'0'),32}");
// 输出:
// 之前: 10000000000000000000000000000000
// 之后: 00010000000000000000000000000000
3.4,无符号右移运算符:
无符号右移运算符 >>> 需要 C# 11 及更高的版本支持, 表示将其左侧操作数向右移动其右侧操作数定义的位数。>>> 运算符始终执行逻辑移位,也就是说无论左侧操作数的类型如何,高顺序空位位置始终设置为零。 如果左侧操作数是带符号类型,>> 运算符将执行算术移位(即最高有效位的值传播到高顺序空位位置)。
示例如下:
// 运算符 >> 和运算符 >>> 的区别:
int x = -8;
Console.WriteLine($"之前: {x,11}, 十六进制: {x,8:x}, 二进制:{Convert.ToString(x, toBase: 2),32}");int y = x >> 2;
Console.WriteLine($"之后 >>: {y,11}, 十六进制: {y,8:x}, 二进制:{Convert.ToString(y, toBase: 2),32}");int z = x >>> 2;
Console.WriteLine($"之后 >>>: {z,11}, 十六进制: {z,8:x}, 二进制:{Convert.ToString(z, toBase: 2).PadLeft(32, '0'),32}");// 输出:
// 之前: -8, 十六进制: fffffff8, 二进制: 11111111111111111111111111111000
// 之后 >>: -2, 十六进制: fffffffe, 二进制: 11111111111111111111111111111110
// 之后 >>>: 1073741822, 十六进制: 3ffffffe, 二进制: 00111111111111111111111111111110
3.5,逻辑与运算符:
& 运算符表示计算其整型操作数的位逻辑 AND; 对 bool 操作数, & 运算符对其操作数执行逻辑 AND 运算;一元 & 运算符是 address-of 运算符。
示例如下:
uint a = 0b_1111_1000;
uint b = 0b_1001_1101;
uint c = a & b;Console.WriteLine(Convert.ToString(c, toBase: 2)); // 输出: 10011000
3.6,逻辑异或运算符:
^ 运算符表示计算其整型操作数的位逻辑异或,也称为位逻辑 XOR; 对于 bool 操作数,^ 运算符对其操作数执行逻辑异或运算。
示例如下:
uint a = 0b_1111_1000;
uint b = 0b_0001_1100;
uint c = a ^ b;Console.WriteLine(Convert.ToString(c, toBase: 2)); // 输出:11100100
3.7,逻辑或运算符:
| 运算符表示计算其整型操作数的位逻辑 OR; 对于 bool 操作数, | 运算符对齐操作数执行逻辑 OR 运算。
示例如下:
uint a = 0b_1010_0000;
uint b = 0b_1001_0001;
uint c = a | b;Console.WriteLine(Convert.ToString(c, toBase: 2)); // 输出: 10110001
4,关系运算符
以下表格展示了相等运算符和比较运算符,其中假设变量 a 为 10,变量 b 为 20:
关系运算符 | 描述 | 实例 |
---|---|---|
== | 相等运算符 | (a == b) 等于 False |
!= | 不等运算符 | (a != b)等于 True |
< | 小于运算符 | (a < b)等于 True |
> | 大于运算符 | (a > b)等于 False |
<= | 小于或等于运算符 | (a <= b)等于 True |
>= | 大于或等于运算符 | (a >= b)等于 False |
4.1,相等运算符:
相等运算符 == 表示测试两个对象是否相等。当内容相等时,值类型相等。当两个变量引用同一内存时,引用类型相等。
示例如下:
// 值类型的比较
int a = 1 + 2 + 3;
int b = 6;
Console.WriteLine(a == b); // 输出: Truechar c1 = 'a';
char c2 = 'A';
Console.WriteLine(c1 == c2); // 输出: False
Console.WriteLine(c1 == char.ToLower(c2)); // 输出: True
// 引用类型的比较
public class ReferenceTypesEquality
{public class MyClass{private int id;public MyClass(int id) => this.id = id;}public static void Main(){var a = new MyClass(1);var b = new MyClass(1);var c = a;Console.WriteLine(a == b); // output: FalseConsole.WriteLine(a == c); // output: True}
}
4.2,不等运算符:
不等于运算符 != 表示当测试的两个对象不相等时,返回 true,否则返回 false。当内容不相等时,值类型不相等。当两个变量引用不同的内存时,引用类型不相等。
示例如下:
int a = 1 + 1 + 2 + 3;
int b = 6;
Console.WriteLine(a != b); // 输出:Truestring s1 = "Hello";
string s2 = "Hello";
Console.WriteLine(s1 != s2); // 输出:Falseobject o1 = 1;
object o2 = 1;
Console.WriteLine(o1 != o2); // 输出:True
// 引用类型的比较
public class ReferenceTypesEquality
{public class MyClass{private int id;public MyClass(int id) => this.id = id;}public static void Main(){var a = new MyClass(1);var b = new MyClass(1);var c = a;Console.WriteLine(a != b); // 输出: TrueConsole.WriteLine(a != c); // 输出: False}
}
4.3,小于运算符:
小于运算符 < 表示如果左侧操作数小于右侧操作数,< 运算符返回 true,否则返回 false。
示例如下:
Console.WriteLine(7.0 < 5.1); // 输出: False
Console.WriteLine(5.1 < 5.1); // 输出: False
Console.WriteLine(0.0 < 5.1); // 输出: True
Console.WriteLine(double.NaN < 5.1); // 输出: False
Console.WriteLine(double.NaN >= 5.1); // 输出: False
4.4,大于运算符:
大于运算符 > 表示如果左侧操作数大于右侧操作数,> 运算符返回 true,否则返回 false。
示例如下:
Console.WriteLine(7.0 > 5.1); // 输出: True
Console.WriteLine(5.1 > 5.1); // 输出: False
Console.WriteLine(0.0 > 5.1); // 输出: False
Console.WriteLine(double.NaN > 5.1); // 输出: False
Console.WriteLine(double.NaN <= 5.1); // 输出: False
4.5,小于或等于运算符:
小于或等于运算符 <= 表示如果左侧操作数小于或等于右侧操作数,<= 运算符返回 true,否则返回 false。
示例如下:
Console.WriteLine(7.0 <= 5.1); // 输出: False
Console.WriteLine(5.1 <= 5.1); // 输出: True
Console.WriteLine(0.0 <= 5.1); // 输出: True
Console.WriteLine(double.NaN > 5.1); // 输出: False
Console.WriteLine(double.NaN <= 5.1); // 输出: False
4.6,大于或等于运算符:
大于或等于运算符 >= 表示如果左侧操作数大于或等于右侧操作数,>= 运算符返回 true,否则返回 false。
示例如下:
Console.WriteLine(7.0 >= 5.1); // 输出: True
Console.WriteLine(5.1 >= 5.1); // 输出: True
Console.WriteLine(0.0 >= 5.1); // 输出: False
Console.WriteLine(double.NaN < 5.1); // 输出: False
Console.WriteLine(double.NaN >= 5.1); // 输出: False
5,赋值运算符
以下表格展示了赋值运算符,其中假设有变量 a 与 b:
赋值运算符 | 描述 | 实例 |
---|---|---|
= | 赋值运算符 | a = b 等同于 b 赋值给 a |
+= | 加且赋值运算符 | a += b 等同于 a = a + b |
-= | 减且赋值运算符 | a -= b 等同于 a = a - b |
*= | 乘且赋值运算符 | a *= b 等同于 a = a * b |
/= | 除且赋值运算符 | a /= b 等同于 a = a / b |
%= | 求模且赋值运算符 | a %= b 等同于 a = a % b |
<<= | 左移且赋值运算符 | a <<= 2 等同于 a = a << 2 |
>>= | 右移且赋值运算符 | a >>= 2 等同于 a = a >> 2 |
&= | 按位与且赋值运算符 | a &= b 等同于 a = a & b |
^= | 按位异或且赋值运算符 | a ^= b 等同于 a = a ^ b |
|= | 按位或且赋值运算符 | a |= b 等同于 a = a | b |
5.1,赋值运算符:
赋值运算符 = 表示将其右操作数的值赋给变量、属性或由其左操作数给出的索引器元素。 赋值表达式的结果是分配给左操作数的值。 右操作数类型必须与左操作数类型相同,或可隐式转换为左操作数的类型。
示例如下:
var numbers = new List<double>() { 1.0, 2.0, 3.0 };
Console.WriteLine(numbers.Capacity); numbers.Capacity = 100;
Console.WriteLine(numbers.Capacity);
// 输出:
// 4
// 100int newFirstElement;
double originalFirstElement = numbers[0];
newFirstElement = 5;
numbers[0] = newFirstElement;Console.WriteLine(originalFirstElement);
Console.WriteLine(numbers[0]);
// 输出:
// 1
// 5
5.2,复合赋值:
对于二元运算符 op,符合赋值表达式 x op= y 等效于 x = x op y。上表中除了简单赋值运算符 = 之外的所有赋值运算符都可以用符合赋值表达式来概括。其中算术、布尔逻辑以及逻辑位和移位运算符支持复合赋值。
示例如下:
class Program
{static void Main(string[] args){int a = 11;int b;b = a;Console.WriteLine("Line 1 - = b 的值 = {0}", b);b += a;Console.WriteLine("Line 2 - += b 的值 = {0}", b);b -= a;Console.WriteLine("Line 3 - -= b 的值 = {0}", b);b *= a;Console.WriteLine("Line 4 - *= b 的值 = {0}", b);b /= a;Console.WriteLine("Line 5 - /= b 的值 = {0}", b);b = 200;b %= a;Console.WriteLine("Line 6 - %= b 的值 = {0}", b);b <<= 2;Console.WriteLine("Line 7 - <<= b 的值 = {0}", b);b >>= 2;Console.WriteLine("Line 8 - >>= b 的值 = {0}", b);b &= 2;Console.WriteLine("Line 9 - &= b 的值 = {0}", b);b ^= 2;Console.WriteLine("Line 10 - ^= b 的值 = {0}", b);b |= 2;Console.WriteLine("Line 11 - |= b 的值 = {0}", b);Console.ReadLine();}
}
6,其他运算符
以下表格展示了 C# 支持的其它一些运算符,其中假设变量 int? a = 10、int[] arr = {1}:
运算符 | 描述 | 实例 |
---|---|---|
sizeof() | sizeof 运算符 | sizeof(int) 返回 4 |
typeof() | typeof 运算符 | typeof(StreamReader) 返回 System.IO.StreamReader |
is | is 运算符 | (a is int) 返回 True |
as | as 运算符 | (a as double?) 返回 null |
? : | 三元条件运算符 | (true ? a : 0) 返回 10 |
??/??= | Null 合并操作符 | (a ?? 0) 返回 10 |
?. /?[] | Null 条件运算符 | arr?[0] 返回 1 |
6.1,sizeof 运算符:
sizeof 运算符表示返回给定类型的变量所占用的字节数。 sizeof 运算符的参数必须是一个非托管类型的名称,或是一个限定为非托管类型的类型参数。 sizeof 运算符需要不安全的上下文。 但在 C# 程序中常见的数据类型会被计算为相应的常数值,并不需要“不安全”的上下文。
示例如下:
Console.WriteLine(sizeof(byte)); // 输出:1
Console.WriteLine(sizeof(short)); // 输出:2
Console.WriteLine(sizeof(ushort)); // 输出:2
Console.WriteLine(sizeof(int)); // 输出:4
Console.WriteLine(sizeof(uint)); // 输出:4
Console.WriteLine(sizeof(long)); // 输出:8
Console.WriteLine(sizeof(ulong)); // 输出:8
Console.WriteLine(sizeof(float)); // 输出:4
Console.WriteLine(sizeof(double)); // 输出:8
Console.WriteLine(sizeof(decimal)); // 输出:16
6.2,typeof 运算符:
typeof 运算符表示用于获取某个类型的 System.Type 实例。 typeof 运算符的实参必须是类型或类型形参的名称。 同时 typeof 运算符的参数不能是需要元数据注释的类型。
示例如下:
Console.WriteLine(typeof(StreamReader)); // 输出: System.IO.StreamReader
//Console.WriteLine(typeof(dynamic)); // 报错:typeof 运算符不能用在xx类型上
6.3,is 运算符
is 运算符表示检查表达式结果的运行时类型是否与给定类型兼容。同时 is 运算符还会对照某个模式测试表达式结果。 E is T 其中 E 是返回一个值的表达式,T 是类型或类型参数的名称。 E 不得为匿名方法或 Lambda 表达式。
示例如下:
public class Base { }public class Derived : Base { }public static class IsOperatorExample
{public static void Main(){object b = new Base();Console.WriteLine(b is Base); // 输出: TrueConsole.WriteLine(b is Derived); // 输出: Falseobject d = new Derived();Console.WriteLine(d is Base); // 输出: TrueConsole.WriteLine(d is Derived); // 输出: True}
}
6.4,as 运算符:
as 运算符表示将表达式结果显式转换为给定的引用或可以为 null 值的类型。 如果无法进行转换,则 as 运算符返回 null。 与强制转换表达式不同,as 运算符永远不会引发异常。同时 as 运算符仅考虑引用、可以为 null、装箱和取消装箱转换。 不能使用 as 运算符执行用户定义的转换。
示例如下:
IEnumerable<int> numbers = new[] { 10, 20, 30 };
IList<int> indexable = numbers as IList<int>;if (indexable != null)
{Console.WriteLine(indexable[0] + indexable[indexable.Count - 1]); // 输出:40
}
6.5,三元条件运算符:
条件运算符 ( ?: ) 也称为三元条件运算符,表示用于计算布尔表达式,并根据布尔表达式的计算结果为 true 还是 false 来返回两个表达式中的一个结果,条件运算符的语法总结为:condition ? consequent : alternative;condition 表达式的计算结果必须为 true 或 false。若 condition 的计算结果为 true,将计算 consequent,其结果成为运算结果。 若 condition 的计算结果为 false,将计算 alternative,其结果成为运算结果。 只会计算 consequent 或 alternative。
示例如下:
string GetWeatherDisplay(double tempInCelsius) => tempInCelsius < 20.0 ? "Cold." : "Perfect!";
Console.WriteLine(GetWeatherDisplay(15)); // 输出: Cold.
Console.WriteLine(GetWeatherDisplay(27)); // 输出: Perfect!
6.6,Null 合并操作符:
Null 合并操作符表示如果左操作数的值不为 null,则 null 合并运算符 ?? 返回该值;否则,它会计算右操作数并返回其结果。 如果左操作数的计算结果为非 null,则 ?? 运算符不会计算其右操作数;仅当左操作数的计算结果为 null 时,Null 合并赋值运算符 ??= 才会将其右操作数的值赋值给其左操作数。 如果左操作数的计算结果为非 null,则 ??= 运算符不会计算其右操作数。
示例如下:
List<int> numbers = null;
int? a = null;
Console.WriteLine((numbers is null)); // 预期: true(numbers ??= new List<int>()).Add(5); // 如果numbers为空,则初始化它。然后,把数字加5Console.WriteLine(string.Join(" ", numbers)); // 输出: 5
Console.WriteLine((numbers is null)); // 预期: false
Console.WriteLine((a is null)); // 预期: true
Console.WriteLine((a ?? 3)); // 预期: 3 因为a仍然是空的// 如果a为空,则将0赋给a并将a添加到列表中
numbers.Add(a ??= 0);
Console.WriteLine((a is null)); // 预期: false
Console.WriteLine(string.Join(" ", numbers)); // 输出: 5 0
Console.WriteLine(a); // 输出: 0
6.7,Null 条件运算符:
Null 条件运算符 ?. 和 ?[] 表示仅当操作数的计算结果为非 NULL 时,NULL 条件运算符才对其操作数应用成员访问 ?. 或元素访问 ?[] 操作;否则,它会返回 null。 即:
- 如果 a 的计算结果为 null,则 a?.x 或 a?[x] 的结果为 null。
- 如果 a 的计算结果为非 null,则 a?.x 或 a?[x] 的结果将分别与 a.x 或 a[x] 的结果相同。
同时 Null 条件运算符采用最小化求职策略。 也就是说如果条件成员或元素访问运算链中的一个运算返回 null,则链的其余部分不会执行。
示例如下:
using System; public class Program
{static double SumNumbers(List<double[]> setsOfNumbers, int indexOfSetToSum){return setsOfNumbers?[indexOfSetToSum]?.Sum() ?? double.NaN;}static void Main(string[] args){var sum1 = SumNumbers(null, 0);Console.WriteLine(sum1); // 输出: NaNvar numberSets = new List<double[]>{new[] { 1.0, 2.0, 3.0 },null};var sum2 = SumNumbers(numberSets, 0);Console.WriteLine(sum2); // 输出: 6var sum3 = SumNumbers(numberSets, 1);Console.WriteLine(sum3); // 输出: NaN }}
7,运算符的优先级
以下表展示了 C# 中运算符的优先级:
类别或名称 | 运算符 |
---|---|
主要 | x.y、f(x)、a[i]、x?.y、x?[y]、x++、x–、x!、new、typeof、checked、unchecked、default、nameof、delegate、sizeof、stackalloc、x->y |
一元 | +x、-x、x、~x、++x、–x、^x、(T)x、await、&&x、*x、true 和 false |
范围 | x…y |
switch 和 with 表达式 | switch、with |
乘法 | x * y、x / y、x % y |
加法 | x + y、x – y |
Shift | x << y、x >> y |
关系和类型测试 | x < y、x > y、x <= y、x >= y、is、as |
相等 | x == y、x != y |
布尔逻辑 AND 或按位逻辑 AND | x & y |
布尔逻辑 XOR 或按位逻辑 XOR | x ^ y |
布尔逻辑 OR 或按位逻辑 OR | x | y |
条件 “与” | x && y |
条件"或" | x || y |
Null 合并运算符 | x ?? y |
条件运算符 | c ? t : f |
赋值和 lambda 声明 | x = y、x += y、x -= y、x *= y、x /= y、x %= y、x &= y、x |= y、x ^= y、x <<= y、x >>= y、x??= y、=> |
7.1,运算符优先级:
运算符优先级表示在包含多个运算符的表达式中,先按优先级较高的运算符计算,再按优先级较低的运算符计算。以下表按最高优先级到最低优先级的顺序列出 C# 运算符, 其中每行中运算符的优先级相同。
示例如下:
var a = 2 + 2 * 2;
Console.WriteLine(a); // 输出:6 var b = (2 + 2) * 2;
Console.WriteLine(b); // 输出:8
- 在包含多个运算符的表达式中,先按优先级较高的运算符计算,再按优先级较低的运算符计算。
- 在此示例中,首先执行乘法,因为其优先级高于加法,使用括号更改运算符优先级所施加的计算顺序。
8,运算符重载
以下表展示了 C# 中可以重载的运算符:
运算符 | 描述 |
---|---|
+x, -x, !x, ~x, ++, --, true, false | true和 false 运算符必须一起重载。 |
x + y, x - y, x * y, x / y, x % y, x & y, x | y, x ^ y, x << y, x >> y, x >>> y | - |
x == y, x != y, x < y, x > y, x <= y, x >= y | 必须按如下方式成对重载: == 和 !=、 < 、 > <= 和 >=。 |
以下表展示了 C# 中不可重载的运算符:
运算符 | 替代方法 |
---|---|
x && y, x || y | 重载 true 和 false 运算符以及 & 或 | 运算符。 |
a[i], a?[i] | 定义索引器。 |
(T)x | 定义可由强制转换表达式执行的自定义类型转换。 |
+=, -=, *=, /=, %=, &=,|=, ^=, <<=, >>=, >>>= | 重载相应的二元运算符。 例如,重载二元 + 运算符时, += 将隐式重载。 |
^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 | 无。 |
8.1,运算符重载的实现:
运算符重载表示用户定义的类型可重载预定义的 C# 运算符。 也就是表示当一个或两个操作数都是某类型时,此类型可提供操作的自定义实现。运算符重载使用 operator 关键字来声明运算符, 运算符声明必须符合以下规则:
- 同时包含 public 和 static 修饰符。
- 一元运算符有一个输入参数。 二元运算符有两个输入参数。 在每种情况下,都至少有一个参数必须具有类型 T 或 T?,其中 T 是包含运算符声明的类型。
同时在 C# 程序并不是所有运算符都可以被重载,上面的两个表就分别介绍了 C# 程序中支持的可重载运算符和不可重载运算符。
示例如下:
// 定义了一个表示有理数的简单结构,该结构会重载一些算术运算符。
public readonly struct Fraction
{private readonly int num;private readonly int den;// 构造函数 public Fraction(int numerator, int denominator){if (denominator == 0){throw new ArgumentException("Denominator cannot be zero.", nameof(denominator)); }num = numerator;den = denominator;}// 运算符重载部分 public static Fraction operator + (Fraction a) => a;public static Fraction operator - (Fraction a) => new Fraction(-a.num,a.den);public static Fraction operator + (Fraction a, Fraction b)=> new Fraction(a.num * b.den + b.num * a.den, a.den * b.den);public static Fraction operator -(Fraction a, Fraction b)=> a + (-b);public static Fraction operator *(Fraction a, Fraction b)=> new Fraction(a.num * b.num, a.den * b.den);public static Fraction operator /(Fraction a, Fraction b){if (b.num == 0){throw new DivideByZeroException();}return new Fraction(a.num * b.den, a.den * b.num);}public override string ToString() => $"{num} / {den}";
}public static class OperatorOverloading
{public static void Main(){var a = new Fraction(5, 4);var b = new Fraction(1, 2);Console.WriteLine(-a); // 输出: -5 / 4Console.WriteLine(a + b); // 输出: 14 / 8Console.WriteLine(a - b); // 输出: 6 / 8Console.WriteLine(a * b); // 输出: 5 / 8Console.WriteLine(a / b); // 输出: 10 / 4}
}
结语
✔️ 以上就是 C# 运算符的总结,希望能够对大家有所帮助。望大家多多支持,你们的支持就是笔者创作最大的动力!
相关文章:
【C#基础】C# 运算符总结
序号系列文章2【C#基础】C# 基础语法解析3【C#基础】C# 数据类型总结4【C#基础】C# 变量和常量的使用文章目录前言运算符1,算术运算符2,布尔逻辑运算符3,位运算符4,关系运算符5,赋值运算符6,其他运算符7&am…...
存储性能软件加速库(SPDK)
存储性能软件加速库SPDK存储加速存储性能软件加速库(SPDK)SPDK NVMe驱动1.用户态驱动1)UIO2)VFIOIOMMU(I/O Memory Management Unit)3)用户态DMA4)大页(Hugepage…...
微服务(五)—— 服务注册中心Consul
一、引入依赖 <dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-consul-discovery</artifactId></dependency>二、配置yml文件 server:port: 8006spring:application:name: cloud-payment-con…...
冷冻电镜 - ChimeraX Density Map 密度图 操作
欢迎关注我的CSDN:https://spike.blog.csdn.net/ 本文地址:https://blog.csdn.net/caroline_wendy/article/details/129055160 由冷冻电镜所生成的Volume,需要观察其内部结构,使用ChimeraX进行操作。 加载Volumes,例如my_volume.mrc 效果如下: 高斯滤波 在命令行(Co…...
Matlab 点云旋转之轴角式
文章目录 一、简介二、实现代码三、实现效果参考资料一、简介 三维空间中表示旋转的方法有很多种,轴角式是其中非常经典的一种表示方式。虽然欧拉角表示旋转的方法很是常用,但欧拉角存在着万向锁这个问题,因此轴角式旋转在旋转使用中更为合适。其原理也很是明了,如下所述:…...
2023美赛数学建模资料思路模型
美赛我们为大家准备了大量的资料,我们会在比赛期间给大家分析美题目和相关的思路 全文都是干货,大家仔细阅读,资料文末自取! 首先我们来看美赛23年题型的一个变化: 美赛23年题目变化: A题:连…...
Nginx配置HTTP强制跳转到HTTPS
https 访问我们的测试域名 https://www.xxx.com 站点,但是当我们直接在浏览器地址栏中直接输入 www.xxx.com 的时候却发现进入的是 http 协议的网站,这与我们的初衷不一致。由于浏览器默认访问域名使用的是80端口,而当我们使用SSL证书后&…...
从实现到原理,聊聊Java中的SPI动态扩展
原创:微信公众号 码农参上,欢迎分享,转载请保留出处。 八股文背多了,相信大家都听说过一个词,SPI扩展。 有的面试官就很喜欢问这个问题,SpringBoot的自动装配是如何实现的? 基本上,…...
3、MySQL字符集
1.MySQL字符集和校验规则 字符集:是一套符号和编码的规则校验规则:是对该套符号和编码的校验,定义字符的排序和比较规则,其中是否区分大小写,跟校验规则有关。2.查看字符集方法 netstat -lntup |grep 3306 tcp6 0 0 :::3306 :::* …...
大漠插件最新中文易语言模块7.2302
模块名称:大漠插件中文模块最新通用7.2302模块简介:大漠插件中文模块最新通用7.2302模块特色:原翻译:花老板完善命令备注:易生易世本人花费一个月时间才将命令完善了插件的备注说明.且用且珍惜去掉了大漠插件定制版类.因为没用.模块特色:什么是中文模块?大漠插件模块是由大漠类…...
极客大挑战 2021
题量很大,收获挺多,持续时间也长,据说结束之后会再持续一段时间,然后题目会开源。 WEB Dark 暗网签到,难以置信 Welcome2021 改个请求方法会提示你文件,再进去就好了 babysql 直接把请求包扔sqlmap里&…...
C#开发的OpenRA加载文件的管理
C#开发的OpenRA加载文件的管理 在前面我们分析了mod.yaml文件,发现里面有很多文件列表, 比如下像下面的文件: Packages: ~^SupportDir|Content/cnc ~^SupportDir|Content/cnc/movies ^EngineDir $cnc: cnc ^EngineDir|mods/common: common ~speech.mix ~conquer.mix ~sounds…...
SSM实现文件上传
目录 SSM实现文件上传 1、修改from表单请求方式改为post,添加属性 2、修改springmvc配置文件,添加一下配置 3、后端方法 SSM实现文件上传 1、修改from表单请求方式改为post,添加属性: enctype"multipart/form-data"…...
OPENCV计算机视觉开发实践-图像的基本概念
1.图像与图形: 图像->客观世界的反映,图与像之结合 图->物体透射光与反射光的分布 像->人的视觉得对图的认识 图像->通过照相,摄像,扫描产生. 图形->通过数学规则产生,或者具有一定规则的图案.用一组符号或线条表示性质. 2.数字图像: 数字图像->称数码图像或…...
Android 9.0 ResolverActivity.java多个app选择界面去掉始终保留仅有一次
1.前言 在9.0的系统rom定制化开发过程中,在系统中安装同类型多个app的时候,在系统启动的过程中,会在启动launcher或播放器的过程中,在启动的过程中都是弹出选择框的,然后在选择启动哪个app,这些选择都是在ResolverActivity.java中完成的,所以需要在ResolverActivity.java…...
【算法 | 例题简答】相关例题讲解
目录 简答题 计算题 时间复杂度的计算 递归算法计算 背包问题(0-1背包问题) 回溯法 动态规划法 编程题 用回溯法解方程 动态规划法解决蜘蛛吃蚊子 用分治法解决抛硬币问题 用二分法分两边求最大值 简答题 1、什么是算法?算法有哪…...
浅谈AQS
1.前言 AQS是AbstractQueuedSynchronizer(抽象同步队列)的简写,它是实现同步器的基础组件,并发包下的锁就是通过AQS实现的。作为开发者可能并不会直接用到AQS,但是知道其原理对于架构设计还是很有帮助的。 那为什么说…...
关于服务连接器(Servlet)你了解多少?
Servlet 1 简介 Servlet是JavaWeb最为核心的内容,它是Java提供的一门动态web资源开发技术。 使用Servlet就可以实现,根据不同的登录用户在页面上动态显示不同内容。 Servlet是JavaEE规范之一,其实就是一个接口,将来我们需要定义…...
面对学员的投诉,中创教育是如何处理的?
客户满意度的检测指标是客户的期望值和服务感知之间的差距。当顾客购买商品时,对商品本身和企业的服务都抱有良好的愿望和期盼值,如果这些愿望和要求得不到满足,就会失去心理平衡,由此产生的抱怨和想"讨个说法"的行为&a…...
算法问题——排序算法问题
摘要 查找和排序算法是算法的入门知识,其经典思想可以用于很多算法当中。因为其实现代码较短,应用较常见。所以在面试中经常会问到排序算法及其相关的问题。但万变不离其宗,只要熟悉了思想,灵活运用也不是难事。一般在面试中最常…...
ArcGIS网络分析之构建网络分析数据集(一)
说明: 1. 本文主要用于演示网络分析服务的搭建过程。所以在此不会深入讨论网络分析服务的每一个细节,本文的目的就是让初学者学会使用网络分析服务进行基本的分析(主要针对后续的WEB开发):路径分析,最近设施点分析,以及服务区分析。 2.关于OD成本矩阵分析,多路径配送,…...
微电影的行业痛点有哪些?
微电影全称微型电影,又称微影。是指能够通过互联网新媒体平台传播(几分钟到60分钟不等)的影片,适合在移动状态、短时休闲状态下观看,具有完整故事情节的“微(超短)时”(几分钟-60分钟)放映、“微(超短)周期制作(7-15天…...
spark3.0源码分析-driver-executor心跳机制
前言 driver和executor心跳机制分为两种机制: 1、executor发送心跳机制 2、driver接受心跳机制 至于为何要分为两种,原因是在分布式场景中,服务的稳定性是无法保障的,例如executor宕机后无法发送心跳,故driver端需要…...
数据分析就要选择这款免费报表工具
对于一家企业来说,在日常运营的过程中本身就会产出很多的数据,那么这些数据本身就应该形成报表。可是如果只是选择手工的一种操作,确实需要浪费大量的人力物力。伴随着科技进入到快速发展的阶段,市面上更是出现了很多报表工具可以…...
node学习-3:服务器渲染和客户端渲染
1. 概念 一.服务端渲染,后端嵌套模板,后端渲染模板,SSR(后端把页面组装好) 做好静态页面,动态效果 把前端代码提供给后端,后端则把静态html以及里面的假数据给删除掉 通过模板进行动态生成h…...
LeetCode刷题笔记和周赛题解总目录
之前一段时间一直在刷LeetCode,在上面积累了很多笔记,这些笔记是做题过程中的一些重要积累和心得,现在将它们汇总和总结至此,此博客将不断更新。 刷题笔记(提供md和pdf两种格式可供下载,不断更新) LeetCode刷题笔记 …...
用类比方式学习编程中函数递归(个人理解仅供参考)(内含汉诺塔问题的求解)
目录 1.前言 2.递归的数学模型 3.相关的c语法 4.将递归的数学模型写成编程语言 5.利用类比方法将实际问题的代码写成函数递归的形式 例1: 例2: 6.汉诺塔问题的求解 1.前言 本人在学习函数递归编程方法的过程中,发现用类比的方式学习递归法可帮助我们在各种编…...
【云原生之Docker实战】使用Docker部署Taskover开源个人任务管理工具
【云原生之Docker实战】使用Docker部署Taskover 开源个人任务管理工具 一、Taskover介绍1.Taskover 简介2.Taskover功能二、检查本地docker环境1.检查系统版本2.检查docker版本3.检查docker状态4.检查docker compose版本三、下载Taskover镜像四、部署Taskover应用1.创建安装目录…...
5、SQL编程开发与注意事项
1.1 导入数据 导入测试库: 文档地址: https://dev.mysql.com/doc/employee/en/sakila-structure.html下载地址: https://github.com/datacharmer/test_db导入测试库: mysql -uroot -p -S < employees.sql 1.2 库操作 增:create database test character set utf8;删:d…...
Allegro如何通过视图显示区分动态和静态铜皮操作指导
Allegro如何通过视图显示区分动态和静态铜皮操作指导 用Allegro做PCB设计的时候,通常动态和静态铜皮是无法通过视图显示区分的,只能通过show element查看得知,如下图 左边铜皮是动态铜皮,右边是静态铜皮 但Allegro可以通过一些设置让动静态铜皮以不同效果显示出来 具体操…...
php网站建设文献综述/天津seo网站推广
转载自:点击打开链接 这是敏捷开发松结对编程系列的第十篇(栏目总目录)。 以下是本人自己及各企业所采用的代码审查的最佳实践,有些数据做了归纳,以使其“更佳”。 请特别注意每个实践最后简单总结的价值观。如果想采用…...
最牛视频网站建设/长沙seo网站推广
你心中的阳光房是什么样的?又宽又厚的钢结构加上钢化玻璃组成的非常笨重的阳光房?冬天还好,可一到夏天升温极快,非常的闷热吗?情愿只做一个阳光顶用来遮阳挡雨也不做阳光房吗?现在这些都是过去式了…...
合肥做网站web0551/十堰seo优化
1.看看demo是怎样的在网上搜索“iOS支付宝sdk”,下载sdk(如图1)图1进入到图2点击左侧移动支付Demo&SDK再点击右侧的iOS&Android版资源,点击右侧SDK&DEMO下载SDK图2下载完成后解压,就得到了这个(…...
怎么做时时彩网站代理/百度seo关键词优化电话
问题描述: 表: Employee ------------------- | Column Name | Type | ------------------- | id | int | | salary | int | ------------------- Id是该表的主键列。 该表的每一行都包含有关员工工资的信息。 编写一个SQL查询来报告 Employee 表…...
上海建设单位工程备案网站/hao123网址导航
从Theano到Lasagne:基于Python的深度学习的框架和库 摘要:最近,深度神经网络以“Deep Dreams”形式在网站中如雨后春笋般出现,或是像谷歌研究原创论文中描述的那样:Inceptionism。在这篇文章中,我们将讨论几…...
珠海seo海网站建设/键词优化排名
操作系统:centos6.4X86_64数据库:oracle12cR1需要的安装包:rlwrap-0.37.tar.gz(网上可下载)readline-6.0-4.el6.x86_64.rpm(镜像包)readline-devel-6.0-4.el6.x86_64.rpm(镜像包&…...