C#本质论笔记 第3章 操作符和控制流

操作符 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
2
3
4
5
6
int x = 123;
int y = 123;
// 输出 123,124,125
System.Console.WriteLine ("{0},{1},{2}", x++, x++, x);
// 输出 124,125,125
System.Console.WriteLine ("{0},{1},{2}", ++y, ++y, y);

选择语句

if-else

下列中,如果 m > 10 不成立,后面代码全部不执行

1
2
3
4
5
6
7
8
9
10
11
12
13
// Try with m = 12 and then with m = 8.
int m = 12;
int n = 18;

if (m > 10)
if (n > 20)
{
Console.WriteLine("Result1");
}
else
{
Console.WriteLine("Result2");
}

下列中,如果 m > 10 不成立,则执行 else 部分代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// Try with m = 12 and then with m = 8.
int m = 12;
int n = 18;

// Try with m = 12 and then with m = 8.
if (m > 10)
{
if (n > 20)
Console.WriteLine("Result1");
}
else
{
Console.WriteLine("Result2");
}

可以将 if 语句嵌套到 else 块中,如以下部分代码所示。

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
// Change the values of these variables to test the results.
bool Condition1 = true;
bool Condition2 = true;
bool Condition3 = true;
bool Condition4 = true;

if (Condition1)
{
// Condition1 is true.
}
else if (Condition2)
{
// Condition1 is false and Condition2 is true.
}
else if (Condition3)
{
if (Condition4)
{
// Condition1 and Condition2 are false. Condition3 and Condition4 are true.
}
else
{
// Condition1, Condition2, and Condition4 are false. Condition3 is true.
}
}
else
{
// Condition1, Condition2, and Condition3 are false.
}

switch

针对 3 个或更多条件测试单个表达式,switch 语句通常用作 if-else 结构的替代项。

示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
using System;

public class Example
{
public static void Main()
{
int caseSwitch = 1;

switch (caseSwitch)
{
case 1:
Console.WriteLine("Case 1");
break;
case 2:
Console.WriteLine("Case 2");
break;
default:
Console.WriteLine("Default case");
break;
}
}
}
// The example displays the following output:
// Case 1

开关部分

C# 不允许从一个开关部分继续执行到下一个开关部分。 因此,以下代码将生成编译器错误。

error CS0163: 控制不能从一个 case 标签(“case 1:”)贯穿到另一个 case 标

1
2
3
4
5
6
7
8
9
10
switch (caseSwitch)
{
// The following switch section causes an error.
case 1:
Console.WriteLine("Case 1...");
// Add a break or other jump statement here.
case 2:
Console.WriteLine("... and/or Case 2");
break;
}

default case

default case 可以在 switch 语句中以任何顺序显示。 无论其在源代码中的顺序如何,都将在对所有 case 标签进行计算之后,最后对其进行计算

匹配表达式

匹配表达式提供与 case 标签中的模式相匹配的值。 语法为:

switch (expr)

在 C# 6 中,匹配表达式必须是返回以下类型值的表达式:

C# 7 开始,匹配表达式可以是任何非 null 表达式。

switch 语句的 模式匹配

每个 case 语句定义一个模式,如果它与匹配表达式相匹配,则会导致执行其包含的开关部分。 所有版本的 C# 都支持常量模式。 其余模式从 C# 7 开始支持。

常量模式

常量模式测试匹配表达式是否等于指定常量。 语法为:

case constant:

其中 constant 是要测试的值。 constant 可以是以下任何常数表达式:

  • bool 文本,为 true 或 false。
  • 任何整数常量,例如 int、long 或字节。
  • 已声明 const 变量的名称。
  • 一个枚举常量。
  • 字符型文本。
  • 字符串文本。

示例

使用常量模式来确定特定日期是否为周末、工作周的第一天、工作周的最后一天或工作周的中间日期。 它根据 DayOfWeek 枚举的成员计算当前日期的 DateTime.DayOfWeek 属性。

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
using System;

class Program
{
static void Main()
{
switch (DateTime.Now.DayOfWeek)
{
case DayOfWeek.Sunday:
case DayOfWeek.Saturday:
Console.WriteLine("The weekend");
break;
case DayOfWeek.Monday:
Console.WriteLine("The first day of the work week.");
break;
case DayOfWeek.Friday:
Console.WriteLine("The last day of the work week.");
break;
default:
Console.WriteLine("The middle of the work week.");
break;
}
}
}
// The example displays output like the following:
// The middle of the work week.

类型模式

类型模式可启用简洁类型计算和转换。 使用 switch 语句执行模式匹配时,会测试表达式是否可转换为指定类型,如果可以,则将其转换为该类型的一个变量。 语法为:

case type varname

示例

使用类型模式来提供有关各种集合类型的信息。

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
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;

class Example
{
static void Main(string[] args)
{
int[] values = { 2, 4, 6, 8, 10 };
ShowCollectionInformation(values);

var names = new List<string>();
names.AddRange( new string[] { "Adam", "Abigail", "Bertrand", "Bridgette" } );
ShowCollectionInformation(names);

List<int> numbers = null;
ShowCollectionInformation(numbers);
}

private static void ShowCollectionInformation(object coll)
{
switch (coll)
{
case Array arr:
Console.WriteLine($"An array with {arr.Length} elements.");
break;
case IEnumerable<int> ieInt:
Console.WriteLine($"Average: {ieInt.Average(s => s)}");
break;
case IList list:
Console.WriteLine($"{list.Count} items");
break;
case IEnumerable ie:
string result = "";
foreach (var item in ie)
result += "${e} ";
Console.WriteLine(result);
break;
case null:
// Do nothing for a null.
break;
default:
Console.WriteLine($"A instance of type {coll.GetType().Name}");
break;
}
}
}
// The example displays the following output:
// An array with 5 elements.
// 4 items

case 语句和 when 子句

从 C# 7 开始,因为 case 语句不需要互相排斥,因此可以添加 when 子句来指定必须满足的附加条件使 case 语句计算为 true。 when 子句可以是返回布尔值的任何表达式。 when 子句的更常见用法之一是防止在匹配表达式的值为 null 时执行开关部分。

据提参见 Microsoft Docs : swittch 关键字 -> case 语句和 when 子句

高级主题:switch case 和 枚举值

直接利用枚举值例子

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
using System;
public class EnumSwitchCase
{
enum Days { Sunday = 6, Monday = 3, Tuesday, Wednesday, Thursday, Friday, Saturday };

static void Main()
{
Days Day = Days.Tuesday;

switch (Day)
{
case Days.Sunday:
Console.WriteLine(Days.Sunday);
break;
case Days.Monday:
Console.WriteLine(Days.Monday);
break;
case Days.Tuesday:
Console.WriteLine(Days.Tuesday);
break;
default:
break;
}

Console.ReadKey();
}
}
/* 输出
Tuesday
*/

枚举值显式显式转换例子

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
using System;
public class EnumTest
{
enum Day { Sunday = 6, Monday = 3, Tuesday, Wednesday, Thursday, Friday, Saturday };

static void Main()
{

int ienum = 4;

switch (ienum)
{
case (int)Day.Sunday:
Console.WriteLine(Day.Sunday);
break;
case (int)Day.Monday:
Console.WriteLine(Day.Monday);
break;
case (int)Day.Tuesday:
Console.WriteLine(Day.Tuesday);
break;
default:
break;
}

Console.ReadKey();
}
}
/* 输出
Tuesday
*/

迭代语句

do

do 语句重复执行一个语句或语句块,直到指定的表达式计算为 false 值。 循环体必须括在大括号 {} 内,除非它由单个语句组成。 在这种情况下,大括号是可选的。

在下面的示例中,只要变量 x 小于 5,do-while 循环语句就开始执行。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public class TestDoWhile
{
public static void Main ()
{
int x = 0;
do
{
Console.WriteLine(x);
x++;
} while (x < 5);
}
}
/*
Output:
0
1
2
3
4
*/

与 while 语句不同的是,do-while 循环会在计算条件表达式之前执行一次。

在 do-while 块中的任何点,都可使用 ==break== 语句跳出循环。 可通过使用 ==continue== 语句直接步入 while 表达式计算语句。 如果 while 表达式计算结果为 true,则继续执行循环中的第一个语句。 如果表达式的计算结果为 false,则继续执行 do-while 循环后的第一个语句。

do-while 循环还可以通过 goto、return 或 throw 语句退出。

while

while 语句执行一条语句或一个语句块,直到指定的表达式的计算结果为 false 为止。

示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
class WhileTest
{
static void Main()
{
int n = 1;
while (n < 6)
{
Console.WriteLine("Current value of n is {0}", n);
n++;
}
}
}
/*
Output:
Current value of n is 1
Current value of n is 2
Current value of n is 3
Current value of n is 4
Current value of n is 5
*/

因为 while 表达式的测试在每次执行循环之前开始,所以 while 循环执行零次或多次。 这不同于 do 循环,该循环执行一次或多次。

break、goto、return 或 throw 语句将控制转移到循环外时,while 循环可能终止。 若要将控制传递到下一个迭代,而不退出循环,则使用 continue 语句。

for

使用 for 循环,可以重复运行一个语句或语句块,直到指定的表达式的计算结果为 false 为止。 这种类型的循环可用于循环==访问数组==,以及==事先知道==循环要在其中进行==循环访问的次数==的其他应用程序。

在下面的示例中,i 的值被写入控制台,并在循环的每次迭代过程中递增 1。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class ForLoopTest
{
static void Main()
{
for (int i = 1; i <= 5; i++)
{
Console.WriteLine(i);
}
}
}
/*
Output:
1
2
3
4
5
*/

因为 while 表达式的测试在每次执行循环之前开始,所以 while 循环执行零次或多次。 这不同于 do 循环,该循环执行一次或多次。

break、goto、return 或 throw 语句将控制转移到循环外时,while 循环可能终止。 若要将控制传递到下一个迭代,而不退出循环,则使用 continue 语句。

下面的示例阐释了几种不太常见的选择:为初始化表达式部分中的外部循环变量赋值、同时在初始化表达式部分和迭代器部分中调用 Console.WriteLine 方法,以及更改迭代器部分中的两个变量的值。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
static void Main()
{
int i;
int j = 10;
for (i = 0, Console.WriteLine("Start: {0}",i); i < j; i++, j--, Console.WriteLine("i={0}, j={1}", i, j))
{
// Body of the loop.
}
}
// Output:
// Start: 0
// i=1, j=9
// i=2, j=8
// i=3, j=7
// i=4, j=6
// i=5, j=5

定义 for 语句的所有表达式都是可选的。 例如,以下语句创建一个无限循环。

1
2
3
4
for (; ; )
{
// ...
}

foreach in

foreach 语句针对实现 System.Collections.IEnumerable 或 System.Collections.Generic.IEnumerable 接口的数组或集合中的每个元素重复一组嵌入语句。

在 foreach 块中的任何点上,可以使用 break 中断关键字中断该循环,或者可以使用 continue 继续关键字单步执行到循环中的下一次迭代。

  • 显示整数数组内容的典型 foreach 循环
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
int[] fibarray = new int[] { 0, 1, 1, 2, 3, 5, 8, 13 };
foreach (int element in fibarray)
{
System.Console.WriteLine(element);
}
System.Console.WriteLine();
// Output:
// 0
// 1
// 1
// 2
// 3
// 5
// 8
// 13
  • 执行相同操作的 for 循环
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
int[] fibarray = new int[] { 0, 1, 1, 2, 3, 5, 8, 13 };
// Compare the previous loop to a similar for loop.
for (int i = 0; i < fibarray.Length; i++)
{
System.Console.WriteLine(fibarray[i]);
}
System.Console.WriteLine();
// Output:
// 0
// 1
// 1
// 2
// 3
// 5
// 8
// 13
  • 维护数组中元素数计数的 foreach 循环
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
int[] fibarray = new int[] { 0, 1, 1, 2, 3, 5, 8, 13 };
// You can maintain a count of the elements in the collection.
int count = 0;
foreach (int element in fibarray)
{
count += 1;
System.Console.WriteLine("Element #{0}: {1}", count, element);
}
System.Console.WriteLine("Number of elements in the array: {0}", count);
// Output:
// Element #1: 0
// Element #2: 1
// Element #3: 1
// Element #4: 2
// Element #5: 3
// Element #6: 5
// Element #7: 8
// Element #8: 13
// Number of elements in the array: 8

因为 while 表达式的测试在每次执行循环之前开始,所以 while 循环执行零次或多次。 这不同于 do 循环,该循环执行一次或多次。

跳转语句

使用跳转语句执行分支,这将立即转移程序控制。 事实上,可以用跳转语句退出循环,或者跳过以此循环的剩余部分并开始下一次循环–即使当前循环条件仍然为true。跳转语句中使用下列关键字:

  • break
  • continue
  • goto
  • return

break

C#使用brek语句退出循环或者switch语句。任何时候遇到break语句,控制都会立即离开循环或者switch。

break 语句将终止其所在位置的最接近封闭循环或 switch 语句。 控制权将传递给已终止语句后面的语句(若有)。

示例

在此示例中,条件语句包含一个应从 1 计数到 100 的计数器;但 break 语句在计数器计数到 4 后终止了循环。

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
class BreakTest
{
static void Main()
{
for (int i = 1; i <= 100; i++)
{
if (i == 5)
{
break;
}
Console.WriteLine(i);
}

// Keep the console open in debug mode.
Console.WriteLine("Press any key to exit.");
Console.ReadKey();
}
}
/*
Output:
1
2
3
4
*/

示例

在此示例中,break 语句用于中断内层嵌套循环,并将控制权返回给外层循环。

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
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
class BreakInNestedLoops
{
static void Main(string[] args)
{

int[] numbers = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
char[] letters = { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j' };

// Outer loop
for (int x = 0; x < numbers.Length; x++)
{
Console.WriteLine("num = {0}", numbers[x]);

// Inner loop
for (int y = 0; y < letters.Length; y++)
{
if (y == x)
{
// Return control to outer loop
break;
}
Console.Write(" {0} ", letters[y]);
}
Console.WriteLine();
}

// Keep the console open in debug mode.
Console.WriteLine("Press any key to exit.");
Console.ReadKey();
}
}

/*
* Output:
num = 0

num = 1
a
num = 2
a b
num = 3
a b c
num = 4
a b c d
num = 5
a b c d e
num = 6
a b c d e f
num = 7
a b c d e f g
num = 8
a b c d e f g h
num = 9
a b c d e f g h i
*/

continue

continue 语句将控制传递到其中出现的封闭 while、do、for 或 foreach 语句的下一次迭代。如果循环条件仍然为 true,循环将继续执行。

示例

在本示例中,计数器最初是从 1 到 10 进行计数。 通过结合使用 continue 语句和表达式 (i < 9),跳过 continue 和 for 主体末尾之间的语句。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
class ContinueTest
{
static void Main()
{
for (int i = 1; i <= 10; i++)
{
if (i < 9)
{
continue;
}
Console.WriteLine(i);
}

// Keep the console open in debug mode.
Console.WriteLine("Press any key to exit.");
Console.ReadKey();
}
}
/*
Output:
9
10
*/

goto

C# 确实支持 goto ,并且,不仅仅可以用在 switch 语句中。

  • goto 语句将程序控制直接传递给标记语句。
  • goto 的一个通常用法是将控制传递给特定的 switch-case 标签或 switch 语句中的默认标签。
  • goto 语句还用于跳出深嵌套循环。

示例

下面的示例演示了 goto 在 switch 语句中的使用。

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
37
38
39
40
41
42
43
44
class SwitchTest
{
static void Main()
{
Console.WriteLine("Coffee sizes: 1=Small 2=Medium 3=Large");
Console.Write("Please enter your selection: ");
string s = Console.ReadLine();
int n = int.Parse(s);
int cost = 0;
switch (n)
{
case 1:
cost += 25;
break;
case 2:
cost += 25;
goto case 1;
case 3:
cost += 50;
goto case 1;
default:
Console.WriteLine("Invalid selection.");
break;
}
if (cost != 0)
{
Console.WriteLine("Please insert {0} cents.", cost);
}
Console.WriteLine("Thank you for your business.");

// Keep the console open in debug mode.
Console.WriteLine("Press any key to exit.");
Console.ReadKey();
}
}
/*
Sample Input: 2

Sample Output:
Coffee sizes: 1=Small 2=Medium 3=Large
Please enter your selection: 2
Please insert 50 cents.
Thank you for your business.
*/

示例

下面的示例演示了使用 goto 跳出嵌套循环。

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
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
public class GotoTest1
{
static void Main()
{
int x = 200, y = 4;
int count = 0;
string[,] array = new string[x, y];

// Initialize the array:
for (int i = 0; i < x; i++)

for (int j = 0; j < y; j++)
array[i, j] = (++count).ToString();

// Read input:
Console.Write("Enter the number to search for: ");

// Input a string:
string myNumber = Console.ReadLine();

// Search:
for (int i = 0; i < x; i++)
{
for (int j = 0; j < y; j++)
{
if (array[i, j].Equals(myNumber))
{
goto Found;
}
}
}

Console.WriteLine("The number {0} was not found.", myNumber);
goto Finish;

Found:
Console.WriteLine("The number {0} is found.", myNumber);

Finish:
Console.WriteLine("End of search.");


// Keep the console open in debug mode.
Console.WriteLine("Press any key to exit.");
Console.ReadKey();
}
}
/*
Sample Input: 44

Sample Output
Enter the number to search for: 44
The number 44 is found.
End of search.
*/

return

return 语句可终止它所在的方法的执行,并将控制权返回给调用方法。 它还可以返回可选值。 如果方法是 void 类型,则 return 语句可以省略

示例

在下面的示例中,该方法CalculateArea()返回局部变量area作为double值

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
class ReturnTest
{
static double CalculateArea(int r)
{
double area = r * r * Math.PI;
return area;
}

static void Main()
{
int radius = 5;
double result = CalculateArea(radius);
Console.WriteLine("The area is {0:0.00}", result);

// Keep the console open in debug mode.
Console.WriteLine("Press any key to exit.");
Console.ReadKey();
}
}
// Output: The area is 78.54

C# 预处理指令

控制流语句中的表达式是在运行时求值。相反,C#预处理器在编译时调用。

#define 和 #undef

使用 #define 来定义符号。 将符号用作传递给 #if 指令的表达式时,该表达式的计算结果为 true,如以下示例所示:

#define DEBUG

还可以通过 /define 编译器选项来定义符号。 可以通过 #undef 取消定义符号。

  • #undef 允许你定义一个符号,这样一来,通过将该符号用作 #if 指令中的表达式,表达式将计算为 false

#if, #elif, #else, 和 #endif

以 #if 指令开头的条件指令必须以 #endif 指令显式终止

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// preprocessor_if.cs
#define DEBUG
#define MYTEST
using System;
public class MyClass
{
static void Main()
{
#if (DEBUG && !MYTEST)
Console.WriteLine("DEBUG is defined");
#elif (!DEBUG && MYTEST)
Console.WriteLine("MYTEST is defined");
#elif (DEBUG && MYTEST)
Console.WriteLine("DEBUG and MYTEST are defined");
#else
Console.WriteLine("DEBUG and MYTEST are not defined");
#endif
}
}

#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
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class MainClass
{
static void Main()
{
#line 200 "Special"
int i; // CS0168 on line 200
int j; // CS0168 on line 201
#line default
char c; // CS0168 on line 9
float f; // CS0168 on line 10
#line hidden // numbering not affected
string s;
double d; // CS0168 on line 13
}
}
  • #line hidden 指令能对调试程序隐藏连续行,当开发者逐行执行代码时,介于 #line hidden 和下一 #line 指令(假设它不是其他 #line hidden 指令)间的任何行都将被跳过。

意思是,调试器会执行 #hidden 后面代码,只是不会在 #hidden 后面代码调试停留。即便设置了断点,也会被调试器忽略。

示例

下列示例演示调试程序如何忽略代码中的隐藏行。 运行示例时,它将显示三行文本。 但是,如果按照示例所示设置断点、并按 F10 逐行执行代码,可观察到调试程序忽略隐藏行。 另请注意,即使在隐藏行设置断点,调试程序仍将忽略它。
C#

1
2
3
4
5
6
7
8
9
10
11
12
13
// preprocessor_linehidden.cs
using System;
class MainClass
{
static void Main()
{
Console.WriteLine("Normal line #1."); // Set break point here.
#line hidden
Console.WriteLine("Hidden line.");
#line default
Console.WriteLine("Normal line #2.");
}
}

运行时输出结果:

Normal line #1.
Hidden line.
Normal line #2.

#pragam

  • #pragma 指令可以启用或者禁用特定的编译警告。

下面例子禁止“字段未使用”警告,然后在编译MyClass类后还原该警告。

1
2
3
4
5
6
#pragma warning disable 169
public class MyClass
{
int neverUsedField;
}
#pragma warning restore 169

若要查找警告编号,请在 Visual Studio 中生成项目,然后在“输出”窗口中查找警告编号。这是要干嘛?😥

结尾

0%