前文:
运算符
包含算术运算符、关系运算符、逻辑运算符、位运算符、赋值运算符及其他运算符。
算数运算符
假设变量 A 的值为 10,变量 B 的值为 20,则:
运算符 | 描述 | 示例 |
---|---|---|
+ |
加 | A + B 将得到 30 |
- |
减 | A - B 将得到 -10 |
* |
乘 | A * B 将得到 200 |
/ |
除 | B / A 将得到 2 |
% |
取模运算符,整除后的余数 | B % A 将得到 0 |
++ |
自增运算符,整数值增加 1 | A++ 将得到 11 |
-- |
自减运算符,整数值减去 1 | A-- 将得到 9 |
对于 a++
和 ++a
的区别:( a--
同理)
int A = 5;
// 后置自增
int result1 = A++; // 先赋值,后自增
Console.WriteLine($"result1: {result1}, A: {A}");
// 输出:
result1: 5, A: 6
int A = 5;
// 前置自增
int result2 = ++A; // 先自增,后赋值
Console.WriteLine($"result2: {result1}, A: {A}");
// 输出:
result2: 6, A: 6
例如:
int a = 21;
int b = 10;
int c;
c = a + b;
Console.WriteLine($"Line 1 - c 的值是 {c}");
c = a - b;
Console.WriteLine($"Line 2 - c 的值是 {c}");
c = a * b;
Console.WriteLine($"Line 3 - c 的值是 {c}");
c = a / b;
Console.WriteLine($"Line 4 - c 的值是 {c}");
c = a % b;
Console.WriteLine($"Line 5 - c 的值是 {c}");
// ++a 先进行自增运算再赋值
c = ++a;
Console.WriteLine($"Line 6 - c 的值是 {c}");
// 此时 a 的值为 22
// --a 先进行自减运算再赋值
c = --a;
Console.WriteLine($"Line 7 - c 的值是 {c}");
输出:
关系运算符
假设变量 A 的值为 10,变量 B 的值为 20,则:
运算符 | 描述 | 示例 |
---|---|---|
== |
检查两个操作数的值是否相等,如果相等则条件为真 | ( A == B ) 不为真 |
!= |
检查两个操作数的值是否相等,如果不相等则条件为真 | ( A != B ) 为真 |
> |
检查左操作数的值是否大于右操作数的值,如果是则条件为真 | ( A > B ) 不为真 |
< |
检查左操作数的值是否小于右操作数的值,如果是则条件为真 | ( A < B ) 为真 |
>= |
检查左操作数的值是否大于或等于右操作数的值,如果是则条件为真 | ( A >= B ) 不为真 |
<= |
检查左操作数的值是否小于或等于右操作数的值,如果是则条件为真 | ( A <= B ) 为真 |
示例:
int a = 21;
int b = 10;
if (a == b) {
Console.WriteLine("Line 1 - a 等于 b");
} else {
Console.WriteLine("Line 1 - a 不等于 b");
}
if (a < b) {
Console.WriteLine("Line 2 - a 小于 b");
} else {
Console.WriteLine("Line 2 - a 不小于 b");
}
if (a > b) {
Console.WriteLine("Line 3 - a 大于 b");
} else {
Console.WriteLine("Line 3 - a 不大于 b");
}
// 改变 a 和 b 的值
a = 5;
b = 20;
if (a <= b) {
Console.WriteLine("Line 4 - a 小于或等于 b");
}
if (b >= a) {
Console.WriteLine("Line 5 - b 大于或等于 a");
}
输出:
Line 1 - a 不等于 b
Line 2 - a 不小于 b
Line 3 - a 大于 b
Line 4 - a 小于或等于 b
Line 5 - b 大于或等于 a
逻辑运算符
假设变量 A 为布尔值 true
,变量 B 为布尔值 false
,则:
运算符 | 描述 | 示例 |
---|---|---|
&& |
与:如果两个操作数都非零,则条件为真 | ( A && B ) 为假 |
|| |
或:如果两个操作数中有任意一个非零,则条件为真 | ( A || B ) 为真 |
! |
非:逆转操作数的逻辑状态,如果条件为真则逻辑非运算符将使其为假 | ( !(A && B) ) 为真 |
示例:
bool a = true;
bool b = true;
if (a && b) {
Console.WriteLine("Line 1 - 条件为真");
}
if (a || b) {
Console.WriteLine("Line 2 - 条件为真");
}
// 改变 a 和 b 的值
a = false;
b = true;
if (a && b) {
Console.WriteLine("Line 3 - 条件为真");
} else {
Console.WriteLine("Line 3 - 条件不为真");
}
if (!(a && b)) {
Console.WriteLine("Line 4 - 条件为真");
}
输出:
Line 1 - 条件为真
Line 2 - 条件为真
Line 3 - 条件不为真
Line 4 - 条件为真
位运算符
位运算符作用于位,并逐位执行操作。&
、 |
、 ^
的真值表如下所示:
p |
q |
p & q |
p | q |
p ^ q |
---|---|---|---|---|
0 | 0 | 0 | 0 | 0 |
0 | 1 | 0 | 1 | 1 |
1 | 1 | 1 | 1 | 0 |
1 | 0 | 0 | 1 | 1 |
假设如果 A = 60,且 B = 13,二进制为:
A = 0011 1100
B = 0000 1101
则:
运算符 | 描述 | 实例 |
---|---|---|
& |
二进制 AND 运算符复制一位到结果中 | ( A & B ) 将得到 12,即为 0000 1100 |
| |
二进制 OR 运算符复制一位到结果中 | ( A | B ) 将得到 61,即为 0011 1101 |
^ |
二进制 运算符复制一位到结果中 | ( A ^ B ) 将得到 49,即为 0011 0001 |
~ |
一元运算符,具有"翻转"位效果,即0变成1,1变成0,包括符号位 | ( ~A ) 将得到 -61,即为 1100 0011,一个有符号二进制数的补码形式 |
<< |
二进制左移运算符,值向左移动指定的位数 | ( A << 2 ) 将得到 240,即为 1111 0000 |
>> |
二进制右移运算符,值向右移动指定的位数 | ( A >> 2 ) 将得到 15,即为 0000 1111 |
示例:
int a = 60; // 60 = 0011 1100
int b = 13; // 13 = 0000 1101 */
int c = 0;
c = a & b; // 12 = 0000 1100
Console.WriteLine($"Line 1 - c 的值是 {c}");
c = a | b; // 61 = 0011 1101
Console.WriteLine($"Line 2 - c 的值是 {c}");
c = a ^ b; // 49 = 0011 0001
Console.WriteLine($"Line 3 - c 的值是 {c}");
c = ~a; // -61 = 1100 0011
Console.WriteLine($"Line 4 - c 的值是 {c}");
c = a << 2; // 240 = 1111 0000
Console.WriteLine($"Line 5 - c 的值是 {c}");
c = a >> 2; // 15 = 0000 1111
Console.WriteLine($"Line 6 - c 的值是 {c}");
输出:
Line 1 - c 的值是 12
Line 2 - c 的值是 61
Line 3 - c 的值是 49
Line 4 - c 的值是 -61
Line 5 - c 的值是 240
Line 6 - c 的值是 15
赋值运算符
运算符 | 描述 | 实例 |
---|---|---|
= |
简单的赋值运算符,把右边的值赋给左边 | C = A + B 将把 A + B 的值赋给 C |
+= |
加且赋值,把右边加上左边的结果赋值给左边 | C += A 相当于 C = C + A |
-= |
减且赋值,把左边减去右边的结果赋值给左边 | C -= A 相当于 C = C - A |
*= |
乘且赋值,把右边乘以左边的结果赋值给左边 | C *= A 相当于 C = C * A |
/= |
除且赋值,把左边除以右边的结果赋值给左边 | C /= A 相当于 C = C / A |
%= |
求模且赋值,求两个操作数的模赋值给左边 | C %= A 相当于 C = C % A |
<<= |
左移且赋值 | C <<= 2 等同于 C = C << 2 |
>>= |
右移且赋值 | C >>= 2 等同于 C = C >> 2 |
&= |
按位与且赋值 | C &= 2 等同于 C = C & 2 |
^= |
按位异或且赋值 | C ^= 2 等同于 C = C ^ 2 |
|= |
按位或且赋值 | C |= 2 等同于 C = C | 2 |
示例:
int a = 21;
int c;
c = a;
Console.WriteLine($"Line 1 - = c 的值 = {c}");
c += a;
Console.WriteLine($"Line 2 - += c 的值 = {c}");
c -= a;
Console.WriteLine($"Line 3 - -= c 的值 = {c}");
c *= a;
Console.WriteLine($"Line 4 - *= c 的值 = {c}");
c /= a;
Console.WriteLine($"Line 5 - /= c 的值 = {c}");
c = 200;
c %= a;
Console.WriteLine($"Line 6 - %= c 的值 = {c}");
c <<= 2;
Console.WriteLine($"Line 7 - <<= c 的值 = {c}");
c >>= 2;
Console.WriteLine($"Line 8 - >>= c 的值 = {c}");
c &= 2;
Console.WriteLine($"Line 9 - &= c 的值 = {c}");
c ^= 2;
Console.WriteLine($"Line 10 - ^= c 的值 = {c}");
c |= 2;
Console.WriteLine($"Line 11 - |= c 的值 = {c}");
输出:
Line 1 - = c 的值 = 21
Line 2 - += c 的值 = 42
Line 3 - -= c 的值 = 21
Line 4 - *= c 的值 = 441
Line 5 - /= c 的值 = 21
Line 6 - %= c 的值 = 11
Line 7 - <<= c 的值 = 44
Line 8 - >>= c 的值 = 11
Line 9 - &= c 的值 = 2
Line 10 - ^= c 的值 = 0
Line 11 - |= c 的值 = 2
其他运算符
运算符 | 描述 | 实例 |
---|---|---|
sizeof() |
返回数据类型的大小 | sizeof(int) 将返回 4 |
typeof() |
返回 class 的类型 | typeof(StreamReader); |
& |
返回变量的地址 | &a; 将得到变量的实际内存地址 |
* |
变量的指针 | *a; 将指向一个变量 |
?: |
条件表达式 | 如果条件为真 ? 则为 X : 否则为 Y |
is |
判断对象是否为某一类型 | if( Ford is Car) 检查 Ford 是否是 Car 类的一个对象 |
as |
强制转换,即使转换失败也不会抛出异常 | Object obj = new StringReader("Hello"); StringReader r = obj as StringReader; |
示例:
// sizeof 运算符的实例
Console.WriteLine($"int 的大小是 {sizeof(int)}");
Console.WriteLine($"short 的大小是 {sizeof(short)}");
Console.WriteLine($"double 的大小是 {sizeof(double)}");
// 三元运算符的实例
int a, b;
a = 10;
b = (a == 1) ? 20 : 30;
Console.WriteLine($"b 的值是 {b}");
b = (a == 10) ? 20 : 30;
Console.WriteLine($"b 的值是 {b}");
输出:
int 的大小是 4
short 的大小是 2
double 的大小是 8
b 的值是 30
b 的值是 20
typeof
关键字用于获取一个类型的类型对象,它通常用于反射和动态创建类型实例:
Type type = typeof(string);
Console.WriteLine(type.FullName);
使用 typeof
关键字来获取 string
类型的类型对象,并将其存储在 Type
类型的变量 type
中,然后,使用 FullName
属性打印该类型的完全限定名,输出:
System.String
运算符优先级
运算符的优先级确定表达式中项的组合,例如 x = 7 + 3 * 2
,在这里,x 被赋值为 13,而不是 20,因为运算符 *
具有比 +
更高的优先级
优先级简易概括:有括号先括号,后乘除在加减,然后位移再关系,逻辑完后条件,最后一个逗号 ,
。
图源自 菜鸟教程。
算术运算符和赋值运算符的优先级:
int a = 10, b = 5, c = 2;
int result = a + b * c; // 先计算乘法,再计算加法
Console.WriteLine(result); // 输出20
result = (a + b) * c; // 先计算加法,再计算乘法
Console.WriteLine(result); // 输出30
a += b * c; // 先计算乘法,再执行加法赋值
Console.WriteLine(a); // 输出20
逻辑运算符的优先级:
bool a = true, b = false, c = true;
bool result = a || b && c; // 先计算与运算,再计算或运算
Console.WriteLine(result); // 输出true
result = (a || b) && c; // 先计算或运算,再计算与运算
Console.WriteLine(result); // 输出true
result = a || (b && c); // 先计算与运算,再计算或运算
Console.WriteLine(result); // 输出true
条件运算符的优先级:
int a = 10, b = 5;
string result = a > b ? "a大于b" : "a不大于b"; // 先判断大小关系,再执行条件语句
Console.WriteLine(result); // 输出"a大于b"
注意:由于括号可以改变运算符优先级,所以在实际应用中建议尽可能使用括号来明确运算顺序,提高代码的可读性和准确性。
判断
判断结构要求程序员指定一个或多个要评估或测试的条件,以及条件为真时要执行的语句(必需的)和条件为假时要执行的语句(可选的)
if语句
用法:
if (布尔表达式)
{
// 如果布尔表达式为真将执行的语句
}
如果布尔表达式为 true,则 if 语句内的代码块将被执行。如果布尔表达式为 false,则 if 语句结束后的第一组代码(闭括号后)将被执行,示例:
int a = 10;
// 使用 if 语句检查布尔条件
if (a < 20)
{
// 如果条件为真,则输出下面的语句
Console.WriteLine("a 小于 20");
}
// 如果条件不为真,则不执行,跳过 if 语句块,继续向下执行代码
Console.WriteLine($"a 的值是 {a}");
输出:
a 小于 20
a 的值是 10
if-else语句
if-else 用法:
if (布尔表达式)
{
// 如果布尔表达式为真将执行的语句
}
else
{
// 如果布尔表达式为假将执行的语句
}
示例:
int a = 100;
// 检查布尔条件
if (a < 20)
{
// 如果条件为真,则输出下面的语句
Console.WriteLine("a 小于 20");
}
else
{
// 如果条件为假,则输出下面的语句
Console.WriteLine("a 大于 20");
}
Console.WriteLine($"a 的值是 {a}");
输出:
a 大于 20
a 的值是 100
if-else if-else用法:
if(布尔表达式1)
{
// 当布尔表达式 1 为真时执行
}
else if(布尔表达式2)
{
// 当布尔表达式 2 为真时执行
}
else if(布尔表达式3)
{
// 当布尔表达式 3 为真时执行
}
else
{
// 当上面条件都不为真时执行
}
注意事项:
- if 后面可以跟 0 或者 多个 else if
- else 必须在 else if 后面
- 一旦某个 else if 匹配成功,其他的 else if 或 else 将不会被测试和执行
示例:
int a = 100;
// 检查布尔条件
if (a == 10)
{
// 如果 if 条件为真,则输出下面的语句
Console.WriteLine("a 的值是 10");
}
else if (a == 20)
{
// 如果 else if 条件为真,则输出下面的语句
Console.WriteLine("a 的值是 20");
}
else if (a == 30)
{
// 如果 else if 条件为真,则输出下面的语句
Console.WriteLine("a 的值是 30");
}
else
{
// 如果上面条件都不为真,则输出下面的语句
Console.WriteLine("没有匹配的值");
}
Console.WriteLine($"a 的准确值是 {a}");
输出:
没有匹配的值
a 的准确值是 100
嵌套 if,else if,顾名思义,就是套娃,用法:
if(布尔表达式1)
{
// 当布尔表达式 1 为真时执行
if(布尔表达式2)
{
// 当布尔表达式 2 为真时执行
// 也就是说,这里的语句只有布尔表达式 1 和 2 都为真才执行
}
}
示例:
int a = 100;
int b = 200;
// 检查布尔条件
if (a == 100)
{
// 如果条件为真,则检查下面的条件
if (b == 200)
{
// 如果条件为真,则输出下面的语句
Console.WriteLine("a 的值是 100,且 b 的值是 200");
}
}
Console.WriteLine($"a 的准确值是 {a}");
Console.WriteLine($"b 的准确值是 {b}");
输出:
a 的值是 100,且 b 的值是 200
a 的准确值是 100
b 的准确值是 200
switch语句
一个 switch 语句允许测试一个变量等于多个值时的情况,每个值称为一个 case,且被测试的变量会对每个 switch case 进行检查,用法:
switch (expression) {
case constant-expression :
statement(s);
break;
case constant-expression :
statement(s);
break;
// 可以有任意数量的 case 语句
default : // 可选的
statement(s);
break;
}
注意事项:
- switch 语句中的 expression 必须是一个 整型或枚举类型,或者是一个 class 类型,其中 class 有一个单一的转换函数将其转换为整型或枚举类型
- 在一个 switch 中可以有任意数量的 case 语句。每个 case 后跟一个要 比较的值和一个冒号
- case 的 constant-expression 必须与 switch 中的变量具有 相同的数据类型,且必须是一个 常量
- 当被测试的变量等于 case 中的常量时,case 后跟的语句将被执行,直到遇到 break 语句为止
- 当遇到 break 语句时,switch 终止,控制流将跳转到 switch 语句后的下一行
- 不是每一个 case 都需要包含 break。如果 case 语句为空,则可以不包含 break,控制流将会 继续 后续的 case,直到遇到 break 为止
- C# 不允许从一个 case 部分继续执行到下一个 case 部分。如果 case 语句中有已经执行,则必须包含 break 或其他跳转语句
- 一个 switch 语句可以有一个可选的 default 语句,在 switch 的结尾。default 语句用于在上面所有 case 都 不为 true 时 执行的一个任务。default 也需要包含 break 语句,这是一个良好的习惯。
- C# 不支持从一个 case 标签显式贯穿到另一个 case 标签。如果要使 C# 支持从一个 case 标签显式贯穿到另一个 case 标签,可以使用
goto
一个 switch-case 或goto default
。
示例1:
int day = 4;
switch (day)
{
case 1:
Console.WriteLine("Monday");
break;
case 2:
Console.WriteLine("Tuesday");
break;
case 3:
Console.WriteLine("Wednesday");
break;
case 4:
Console.WriteLine("Thursday");
break;
case 5:
Console.WriteLine("Friday");
break;
case 6:
Console.WriteLine("Saturday");
break;
case 7:
Console.WriteLine("Sunday");
break;
default :
Console.WriteLine("日期错误");
break;
}
输出:
Thursday
示例2:
char grade = 'B';
switch (grade)
{
case 'A':
Console.WriteLine("很棒!");
break;
case 'B':
case 'C':
Console.WriteLine("做得好");
break;
case 'D':
Console.WriteLine("您通过了");
break;
case 'F':
Console.WriteLine("最好再试一下");
break;
default:
Console.WriteLine("无效的成绩");
break;
}
Console.WriteLine($"您的成绩是 {grade}");
输出:
做得好
您的成绩是 B
case B 内容为空,跳到了 case C,并且执行了 case C 中的语句,直到遇到了 case C 中的 break 才跳出 switch 语句。
switch 和 if 语句一样支持嵌套,可以把一个 switch 作为一个外部 switch 的语句序列的一部分,即可以在一个 switch 语句内使用另一个 switch 语句,即使内部和外部 switch 的 case 常量包含共同的值,也没有矛盾。例如:
int a = 100;
int b = 200;
switch (a)
{
case 100:
Console.WriteLine("这是外部 switch 的一部分");
switch (b)
{
case 200:
Console.WriteLine("这是内部 switch 的一部分");
break;
}
break;
}
Console.WriteLine($"a 的准确值是 {a}");
Console.WriteLine($"b 的准确值是 {b}");
输出:
这是外部 switch 的一部分
这是内部 switch 的一部分
a 的准确值是 100
b 的准确值是 200
条件运算符
前文中的 ? :
运算符的功能和简单的 if else 的功能一样,例如:
int a, b;
a = 10;
b = (a == 1) ? 20 : 30;
Console.WriteLine($"b 的值是 {b}");
b = (a == 10) ? 20 : 30;
Console.WriteLine($"b 的值是 {b}");
输出:
b 的值是 30
b 的值是 20