C# 预处理器指令

C# 预处理器指令

概述

预处理器指令:是编程语言中的一种特殊语法,用于在源代码编译之前对代码进行预处理。

C# 预处理器指令 与 C/C++ 预处理器指令的区别

1. C# 不支持宏定义

C# 的预处理器指令主要用于条件编译,不支持像 C/C++ 那样的宏定义。

C# 示例:

#define DEBUG
using System;
class Program
{
static void Main()
{
#if DEBUG
Console.WriteLine("Debug mode is enabled.");
#else
Console.WriteLine("Release mode is enabled.");
#endif
}
}

C/C++ 示例:

#define PI 3.14159
#define MAX(a, b) ((a) > (b) ? (a) : (b))
int main() {
double radius = 5.0;
double area = PI * radius * radius; // 使用宏定义的 PI
int x = 10, y = 20;
int maxValue = MAX(x, y); // 使用宏定义的 MAX 函数
return 0;
}

2. C# 预处理器指令必须独占一行

在 C# 中,预处理器指令必须独占一行,不能与其他代码混合在同一行。

C# 示例:

#define DEBUG
int radius = 5.0;

C/C++ 示例:

#define PI 3.14159 int radius = 5.0; // 不推荐,尽管编译器可能接受

3. C# 不支持文件包含指令

C# 不支持 #include 指令,使用 using 指令来引入命名空间。

C# 示例:

using System;
class Program
{
static void Main()
{
Console.WriteLine("Hello, World!");
}
}

C/C++ 示例:

#include <iostream>
#include <vector>
int main() {
std::cout << "Hello, World!" << std::endl;
std::vector<int> numbers = {1, 2, 3, 4, 5};
for (int number : numbers) {
std::cout << number << std::endl;
}
return 0;
}

4. C# 编译器直接处理

C# 编译器没有独立的预处理器,但编译器在编译过程中会直接处理预处理器指令。

在 C/C++ 中,预处理器是一个独立的工具,负责在编译之前处理源代码。

指令

可为空上下文

#nullable指令用于控制代码中的可空上下文。

1. #nullable disable

  • 在此指令之后的代码中,可空性检查将被禁用

#nullable disable 会同时禁用可空性注释(annotations)和可空性警告(warnings)

#nullable disable

默认是启用可空性检查的:

图片失效即显示

我们添加#nullable disable指令后:

图片失效即显示
  • 在此指令之后的代码中,可空注释将被忽略
#nullable disable annotations
  • 在此指令之后的代码中,可空性相关的警告将被禁用
#nullable disable warnings

我们添加#nullable disable warnings指令后:

2. #nullable enable

  • 在此指令之后的代码中,可空性检查将被启用

#nullable enable 会同时启用可空性注释(annotations)和可空性警告(warnings)

#nullable enable
  • 在此指令之后的代码中,可空注释将被启用
#nullable enable annotations
  • 在此指令之后的代码中,可空性相关的警告将被启用
#nullable enable warnings

3. #nullable resotre

  • 在此指令之后的代码中,可空性检查将遵循项目的默认设置

#nullable resotre 会同时设置可空性注释(annotations)和可空性警告(warnings)遵循项目的默认设置

#nullable resotre
  • 在此指令之后的代码中,可空注释将遵循项目的默认设置
#nullable resotre annotations
  • 在此指令之后的代码中,可空性相关的警告将遵循项目的默认设置
#nullable resotre warnings

条件编译指令

条件编译指令有:#if#else#elif#elseif#endif#define#undef

  1. #if

    • 用于开始一个条件编译块。
    • 必须与 #endif 配对使用,以明确结束条件编译块。
#define DEBUG
#if DEBUG
Console.WriteLine("DEBUG");
#endif
  1. #else

    • 用于提供一个替代代码块,当 #if 条件不满足时执行。
    • 必须紧跟在 #if 或 #elif 后面。
#if DEBUG
Console.WriteLine("DEBUG");
#else
Console.WriteLine("NOT DEBUG");
#endif
  1. #elif

    • 等效于 else if,用于提供多个条件分支。
    • 可以有多个 #elif,但必须紧跟在 #if 或另一个 #elif 后面。
#define VC7
#if DEBUG
Console.WriteLine("DEBUG");
#elif VC7
Console.WriteLine("VC7");
#endif
  1. #endif

    • 标记一个条件编译块的结束。
    • 每个 #if 必须有一个对应的 #endif。
#define DEBUG
#if DEBUG
Console.WriteLine("DEBUG");
#endif
  1. #define

    • 定义一个符号,在后续的条件编译中该符号被视为 true。
#define DEBUG
  • 必须出现在文件中所有非预处理器指令之前。
#define DEBUG
#undef TRACE
using System;
public class TestDefine
{
public static void Main()
{
#if DEBUG
Console.WriteLine("DEBUG");
#endif
#if TRACE
Console.WriteLine("TRACE");
#endif
}
}

可以使用运算符 == (相等)、!= (不相等)、&&(和)、||(或)以及 !(非)运算符来计算符号是否定义。

例如:

#define VC7
using System;
public class Program
{
public static void Main()
{
#if (VC7 || DEBUG)
Console.WriteLine("VC7 or DEBUG is defined");
#endif
}
}
  1. #undef

    • 删除一个已定义的符号,在后续的条件编译中该符号被视为 false。
#undef DEBUG
  • 必须出现在文件中所有非预处理器指令之前。
#undef DEBUG
using System;
public class TestUndef
{
public static void Main()
{
#if DEBUG
Console.WriteLine("DEBUG");
#else
Console.WriteLine("NOT DEBUG");
#endif
}
}

代码组织指令

代码组织指令有:#region#endregion

用于将代码逻辑分组,便于折叠和展开代码块,提高代码可读性。

#region para
private static readonly int _count = 100;
#endregion
#region func
private static void SayHello()
{
Console.WriteLine("Hello World!");
}
#endregion
图片失效即显示

在编译器中可以折叠代码区域

图片失效即显示

警告和错误指令

警告和错误指令有:#warning#error#line

  1. #warning

    • 在编译时生成警告信息。
#warning "This code is deprecated and will be removed in future versions."
  1. 调试代码
图片失效即显示
  1. 在构建输出窗口中给出警告信息
图片失效即显示
  1. #error

    • 在编译时生成错误信息,阻止编译继续。
#error "This feature is not supported in this environment."

调试代码,在构建输出窗口中给出错误信息

图片失效即显示
  1. #line

    • 用于修改调试器显示的行号信息,常用于生成代码或宏扩展。
#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

调试代码,在构建输出窗口中给出警告信息

图片失效即显示

编译器指令

#pragma 为编译器提供特殊的指令,以说明如何编译包含杂注的文件。

Microsoft C# 编译器支持以下两个 #pragma 指令:

  • #pragma warning

  • #pragma checksum

#pragma 指令的语法为:

#pragma pragma-name pragma-arguments
  • pragma-name:识别杂注的名称。warning/checksum

  • pragma-arguments:特定于杂注的参数。

  1. #pragma warning

语法:

#pragma warning disable warning-list
#pragma warning restore warning-list

参数:

warning-list // 警告编号的逗号分隔列表。只输入数字,不包括前缀 "CS"。

当没有指定警告编号时,disable 禁用所有警告,而 restore 启用所有警告。

图片失效即显示
  1. #pragma checksum

该指令用于在编译时为源文件生成校验和信息,这些信息会被嵌入到程序数据库(PDB)文件中。校验和信息主要用于调试器,以确保调试器加载的源代码与编译时的源代码一致。

语法:

#pragma checksum "filename" "{guid}" "checksum bytes"

参数:

"filename" // 要求监视更改或更新的文件的名称。
"{guid}" // 文件的全局唯一标识符 (GUID)。
"checksum_bytes" // 十六进制数的字符串,表示校验和的字节。必须是偶数位的十六进制数。奇数位的十六进制数字会导致编译时警告,然后指令被忽略。

示例:

namespace CodeExecutor;
#pragma checksum "Program.cs" "{88FBCA52-7B47-4D4B-9B9C-61F35F8E5A8C}" "4A5B6C7D"
public static class Program
{
public static void Main(string[] args)
{
Console.WriteLine("Hello, World!");
}
}

源文件Program.cs编译时生成的校验和信息被嵌入.pdf文件中:

图片失效即显示

文章引用

  1. 微软官方文档 - C# 预处理器指令
    https://learn.microsoft.com/zh-cn/dotnet/csharp/language-reference/preprocessor-directives

  2. MSDN C# 编程指南 & 参考手册 2015 - C# 预处理器指令
    https://wizardforcel.gitbooks.io/msdn-csharp/content/ref/200.html

文章声明

内容准确性: 我会尽力确保所分享信息的准确性和可靠性,但由于个人知识有限,难免会有疏漏或错误。如果您在阅读过程中发现任何问题,请不吝赐教,我将及时更正。
AI: 文章内容参考了DeepSeek、智谱清言、通义灵码大语言模型生成的内容。

posted on   wubing7755  阅读(22)  评论(0编辑  收藏  举报

相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
< 2025年3月 >
23 24 25 26 27 28 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 1 2 3 4 5

统计

点击右上角即可分享
微信分享提示