操作符 Operators
操作符,也叫运算符,英文:Operrators,见 Microsoft Docs C# 运算符。
名称 | 含义 | 例子 |
---|---|---|
一元运算符 | 接受一个操作数的运算符 | ++ 或 new |
二元运算符 | 接受两个操作数的运算符 | + - * / |
三元运算符 | 接受三个操作数,C#中唯一的条件运算符 | ?: |
一元操作符
表达式 | 描述 | 说明 |
---|---|---|
+x | 标识 | +5 ,正号,无意义,出于对 - 操作符的对称才加进来的 |
-x | 求反 | -5 ,负号,等价于从零减去操作数 |
! | 逻辑求反 | 它针对 bool 定义,当且仅当其操作数为 false 时返回 true。 |
~x | 按位求反 | 影响操作数的每一个位(bit) |
++x | 前递增 | 操作的结果是操作数递增后 的值。 |
x++ | 后递增 | 操作的结果是操作数递增前 的值。 |
--x |
前递减 | 操作的结果是操作数递减后 的值。 |
x-- |
后递减 | 操作的结果是操作数递减前 的值。 |
(T)x | 将 x 显式转换为类型 T | 指定强制转换或类型转换。 |
递增和递减操作符 ++
--
递增运算符(Post-Increment)++
按 1 递增其操作数。 递增运算符可以在其操作数之前或之后出现: ++variable 和 variable++。第一种形式是前缀递增操作。 操作的结果是操作数递增后的值。 第二种形式是后缀递增操作。 操作的结果是操作数递增前的值。
递减运算符 (Post-Decrement) --
按 1 递减其操作数。 减量运算符可以在其操作数之前或之后出现:–variable 和 variable–。 第一种形式是前缀递减操作。 操作的结果是操作数递减后的值。 第二种形式是后缀递减操作。 操作的结果是操作数递减前的值。
1 | int x = 123; |
选择语句
if-else
下列中,如果 m > 10 不成立,后面代码全部不执行
1 | // Try with m = 12 and then with m = 8. |
下列中,如果 m > 10 不成立,则执行 else 部分代码
1 | // Try with m = 12 and then with m = 8. |
可以将 if 语句嵌套到 else 块中,如以下部分代码所示。
1 | // Change the values of these variables to test the results. |
switch
针对 3 个或更多条件测试单个表达式,switch 语句通常用作 if-else 结构的替代项。
示例
1 | using System; |
开关部分
C# 不允许从一个开关部分继续执行到下一个开关部分。 因此,以下代码将生成编译器错误。
error CS0163: 控制不能从一个 case 标签(“case 1:”)贯穿到另一个 case 标
签
1 | switch (caseSwitch) |
default case
default case 可以在 switch 语句中以任何顺序显示。 无论其在源代码中的顺序如何,都将在对所有 case 标签进行计算之后,最后对其进行计算。
匹配表达式
匹配表达式提供与 case 标签中的模式相匹配的值。 语法为:
switch (expr)
在 C# 6 中,匹配表达式必须是返回以下类型值的表达式:
从 C# 7 开始,匹配表达式可以是任何非 null 表达式。
switch 语句的 模式匹配
每个 case 语句定义一个模式,如果它与匹配表达式相匹配,则会导致执行其包含的开关部分。 所有版本的 C# 都支持常量模式。 其余模式从 C# 7 开始支持。
常量模式
常量模式测试匹配表达式是否等于指定常量。 语法为:
case constant:
其中 constant 是要测试的值。 constant 可以是以下任何常数表达式:
示例
使用常量模式来确定特定日期是否为周末、工作周的第一天、工作周的最后一天或工作周的中间日期。 它根据 DayOfWeek 枚举的成员计算当前日期的 DateTime.DayOfWeek 属性。
1 | using System; |
类型模式
类型模式可启用简洁类型计算和转换。 使用 switch 语句执行模式匹配时,会测试表达式是否可转换为指定类型,如果可以,则将其转换为该类型的一个变量。 语法为:
case type varname
示例
使用类型模式来提供有关各种集合类型的信息。
1 | using System; |
case 语句和 when 子句
从 C# 7 开始,因为 case 语句不需要互相排斥,因此可以添加 when 子句来指定必须满足的附加条件使 case 语句计算为 true。 when 子句可以是返回布尔值的任何表达式。 when 子句的更常见用法之一是防止在匹配表达式的值为 null 时执行开关部分。
据提参见 Microsoft Docs : swittch 关键字 -> case 语句和 when 子句
高级主题:switch case 和 枚举值
直接利用枚举值例子
1 | using System; |
枚举值显式显式转换例子
1 | using System; |
迭代语句
do
do 语句重复执行一个语句或语句块,直到指定的表达式计算为 false 值。 循环体必须括在大括号 {} 内,除非它由单个语句组成。 在这种情况下,大括号是可选的。
在下面的示例中,只要变量 x 小于 5,do-while 循环语句就开始执行。
1 | public class TestDoWhile |
与 while 语句不同的是,do-while 循环会在计算条件表达式之前执行一次。
在 do-while 块中的任何点,都可使用 ==break== 语句跳出循环。 可通过使用 ==continue== 语句直接步入 while 表达式计算语句。 如果 while 表达式计算结果为 true,则继续执行循环中的第一个语句。 如果表达式的计算结果为 false,则继续执行 do-while 循环后的第一个语句。
do-while 循环还可以通过 goto、return 或 throw 语句退出。
while
while 语句执行一条语句或一个语句块,直到指定的表达式的计算结果为 false 为止。
示例
1 | class WhileTest |
因为 while 表达式的测试在每次执行循环之前开始,所以 while 循环执行零次或多次。 这不同于 do 循环,该循环执行一次或多次。
break、goto、return 或 throw 语句将控制转移到循环外时,while 循环可能终止。 若要将控制传递到下一个迭代,而不退出循环,则使用 continue 语句。
for
使用 for 循环,可以重复运行一个语句或语句块,直到指定的表达式的计算结果为 false 为止。 这种类型的循环可用于循环==访问数组==,以及==事先知道==循环要在其中进行==循环访问的次数==的其他应用程序。
在下面的示例中,i 的值被写入控制台,并在循环的每次迭代过程中递增 1。
1 | class ForLoopTest |
因为 while 表达式的测试在每次执行循环之前开始,所以 while 循环执行零次或多次。 这不同于 do 循环,该循环执行一次或多次。
break、goto、return 或 throw 语句将控制转移到循环外时,while 循环可能终止。 若要将控制传递到下一个迭代,而不退出循环,则使用 continue 语句。
下面的示例阐释了几种不太常见的选择:为初始化表达式部分中的外部循环变量赋值、同时在初始化表达式部分和迭代器部分中调用 Console.WriteLine 方法,以及更改迭代器部分中的两个变量的值。
1 | static void Main() |
定义 for 语句的所有表达式都是可选的。 例如,以下语句创建一个无限循环。
1 | for (; ; ) |
foreach in
foreach 语句针对实现 System.Collections.IEnumerable 或 System.Collections.Generic.IEnumerable
在 foreach 块中的任何点上,可以使用 break 中断关键字中断该循环,或者可以使用 continue 继续关键字单步执行到循环中的下一次迭代。
- 显示整数数组内容的典型 foreach 循环
1 | int[] fibarray = new int[] { 0, 1, 1, 2, 3, 5, 8, 13 }; |
- 执行相同操作的 for 循环
1 | int[] fibarray = new int[] { 0, 1, 1, 2, 3, 5, 8, 13 }; |
- 维护数组中元素数计数的 foreach 循环
1 | int[] fibarray = new int[] { 0, 1, 1, 2, 3, 5, 8, 13 }; |
因为 while 表达式的测试在每次执行循环之前开始,所以 while 循环执行零次或多次。 这不同于 do 循环,该循环执行一次或多次。
跳转语句
使用跳转语句执行分支,这将立即转移程序控制。 事实上,可以用跳转语句退出循环,或者跳过以此循环的剩余部分并开始下一次循环–即使当前循环条件仍然为true。跳转语句中使用下列关键字:
- break
- continue
- goto
- return
break
C#使用brek语句退出循环或者switch语句。任何时候遇到break语句,控制都会立即离开循环或者switch。
break 语句将终止其所在位置的最接近封闭循环或 switch 语句。 控制权将传递给已终止语句后面的语句(若有)。
示例
在此示例中,条件语句包含一个应从 1 计数到 100 的计数器;但 break 语句在计数器计数到 4 后终止了循环。
1 | class BreakTest |
示例
在此示例中,break 语句用于中断内层嵌套循环,并将控制权返回给外层循环。
1 | class BreakInNestedLoops |
continue
continue 语句将控制传递到其中出现的封闭 while、do、for 或 foreach 语句的下一次迭代。如果循环条件仍然为 true,循环将继续执行。
示例
在本示例中,计数器最初是从 1 到 10 进行计数。 通过结合使用 continue 语句和表达式 (i < 9),跳过 continue 和 for 主体末尾之间的语句。
1 | class ContinueTest |
goto
C# 确实支持 goto ,并且,不仅仅可以用在 switch 语句中。
- goto 语句将程序控制直接传递给标记语句。
- goto 的一个通常用法是将控制传递给特定的 switch-case 标签或 switch 语句中的默认标签。
- goto 语句还用于跳出深嵌套循环。
示例
下面的示例演示了 goto 在 switch 语句中的使用。
1 | class SwitchTest |
示例
下面的示例演示了使用 goto 跳出嵌套循环。
1 | public class GotoTest1 |
return
return 语句可终止它所在的方法的执行,并将控制权返回给调用方法。 它还可以返回可选值。 如果方法是 void 类型,则 return 语句可以省略。
示例
在下面的示例中,该方法CalculateArea()返回局部变量area作为double值
1 | class ReturnTest |
C# 预处理指令
控制流语句中的表达式是在运行时求值。相反,C#预处理器在编译时调用。
#define 和 #undef
使用 #define 来定义符号。 将符号用作传递给 #if 指令的表达式时,该表达式的计算结果为 true,如以下示例所示:
#define DEBUG
还可以通过 /define 编译器选项来定义符号。 可以通过 #undef 取消定义符号。
- #undef 允许你定义一个符号,这样一来,通过将该符号用作 #if 指令中的表达式,表达式将计算为 false。
#if, #elif, #else, 和 #endif
以 #if 指令开头的条件指令必须以 #endif 指令显式终止
1 | // preprocessor_if.cs |
#warning 和 #error
- #warning 可从代码中的特定位置生成一个级别的警告。
- #error 可从代码中的特定位置生成错误。
- 编译器遇到 #warning 指令,会显示 #warning 指令后面的文本,然后继续编译。
- 编译器遇到 #error 指令,会显示后面的文本,然后立即退出编译,不会生成IL代码。
#region 和 #endregion
利用 #region 和 #endregion,可以指定在使用 Visual Studio 编辑器的大纲功能时可展开或折叠的代码块。
- #region 块必须通过 #endregion 指令终止。
- #region 块不能与 #if 块重叠。 但是,可以将 #region 块嵌套在 #if 块内,或将 #if 块嵌套在 #region 块内。
#line
- #line 可修改编译器的行号及(可选)用于错误和警告的文件名输出。
此示例演示如何报告与行号相关联的两个警告。 #line 200 指令将行号强制设为 200(尽管默认值为 #7),直到下一个 #line 指令前,文件名都将报告为“特殊”。 #line 默认指令将行号返回至其默认行号,默认行号对由上个指令重新编号的行进行计数。
1 | class MainClass |
- #line hidden 指令能对调试程序隐藏连续行,当开发者逐行执行代码时,介于 #line hidden 和下一 #line 指令(假设它不是其他 #line hidden 指令)间的任何行都将被跳过。
意思是,调试器会执行 #hidden 后面代码,只是不会在 #hidden 后面代码调试停留。即便设置了断点,也会被调试器忽略。
示例
下列示例演示调试程序如何忽略代码中的隐藏行。 运行示例时,它将显示三行文本。 但是,如果按照示例所示设置断点、并按 F10 逐行执行代码,可观察到调试程序忽略隐藏行。 另请注意,即使在隐藏行设置断点,调试程序仍将忽略它。
C#
1 | // preprocessor_linehidden.cs |
运行时输出结果:
Normal line #1.
Hidden line.
Normal line #2.
#pragam
- #pragma 指令可以启用或者禁用特定的编译警告。
下面例子禁止“字段未使用”警告,然后在编译MyClass类后还原该警告。
1 |
|
若要查找警告编号,请在 Visual Studio 中生成项目,然后在“输出”窗口中查找警告编号。这是要干嘛?😥