百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术分析 > 正文

2.1.5 C#8.0教程 - 预处理指令 预处理指令的位置

liebian365 2024-10-18 09:35 3 浏览 0 评论

如果你熟悉 C语言 或它的直系衍生语言,你一定了解预处理器的基本概念。那么 C# 是否提供了预处理器?结论是:它没有单独的预处理阶段,也不提供宏。然而,它确实有一些类似于 C语言 预处理器提供的指令,尽管它的选择非常有限。尽管 C# 不像 C 一样有完整的预处理阶段,但是这些被称为预处理指令。本课将会提到一些常用的指令。

  1. 编译符号
  2. #error 与 #warning
  3. #line
  4. #pragma
  5. #nullable
  6. #region and #endregion

编译符号

C# 提供了一个 #define 指令,可以让你定义编译符号。这些符号通常与 #if 指令一起使用,以不同的方式针对不同的情况编译代码。例如,你可能希望某些代码只出现在调试中,或者你可能需要在不同的平台上使用不同的代码来实现特定的效果。通常,你不会使用 #define 指令,但更常见的是通过编译器构建设置来定义编译符号。要对此进行控制,可以直接打开 .csproj 项目文件,在 PropertyGroup 中的 DefineConstants 元素中定义需要的值。

.NET SDK 定义了某些默认符号。它支持两种配置:调试Debug 和 发布Release。它在调试配置中定义 DEBUG 编译符号,而在发布中定义了 RELEASE。在两种配置中定义了一个两者共有的称为 TRACE 的符号。某些项目类型使用额外的符号。例如,针对 .NET Standard 2.0 将同时定义NETSTANDARD 和 NETSTANDARD2_0。

编译符号通常与 #if、#else、#elif 和 #endif 指令一起使用(#elif是else if的缩写)。例5.1 使用其中一些指令来确保某些代码行只在调试版本中编译。(你还可以编写#if false来完全防止代码段被编译。这通常只是作为一种临时措施,是注释的替代方法,避免了试图嵌套注释时的词汇陷阱。)

// 示例 5.1
static void Main(string[] args)
{
    #if RELEASE
        Console.WriteLine("RELEASE ...");
    #endif
    #if DEBUG
        Console.WriteLine("DEBUG ...");
    #endif
}

c#提供了一种更微妙的机制来支持这类事情,称为条件方法。编译器识别.NET类库定义的称为ConditionalAttribute的属性,并为其提供特殊的 编译时compile-time 行为。你可以给任何方法用此属性注释。例5.2 使用它表示只有在定义了调试编译符号时才应该使用带注释的方法。

// 示例 5.2
static void Main(string[] args)
{
    ShowDebugInfo();
    ShowReleaseInfo();
}

[System.Diagnostics.Conditional("DEBUG")]
static void ShowDebugInfo()
{
    Console.WriteLine("Conditional DEBUG ...");
}

[System.Diagnostics.Conditional("RELEASE")]
static void ShowReleaseInfo()
{
    Console.WriteLine("Conditional RELEASE ...");
}

注意对比图2 、图3的两个条件方法,一个是在 Debug 阶段运行的,一个是在 Release 阶段运行的。

特别要注意输出面板,分别输出了 “Conditional DEBUG ...” 和 “Conditional RELEASE ...”。说明条件方法在起作用。

另外要特别理解的是,如果您编写的代码调用了这样注释的方法,c#编译器将在没有定义相关符号的编译中忽略该调用。因此,如果你编写代码来调用这两个 ShowDebugInfo / ShowReleaseInfo 方法,编译器会在编译中删除另外一个调用方法,但不会使用指令使代码混乱。

.NET类库中的 Debug类 和 Trace类 在System.Diagnostics命名空间使用此特性。Debug类提供了各种以调试编译符号为条件的方法,而Trace类有以跟踪为条件的方法。如果保留新C#项目的默认设置,那么通过Trace类生成的任何诊断输出都将在调试和发布版本中可用,但是调用Debug类上的方法的任何代码都不会编译到发布版本中。

#error 与 #warning

C# 允许您使用 #error#warning 指令来选择生成编译器错误或警告。这些通常在条件区域内使用,如例2-30所示,当然一个无条件执行的 #warning 可以用来提醒自己还没有编写一些特别重要的代码。

// 示例 5.3
static void Main(string[] args)
{
    #warning 当您运行此代码后,您有权保持沉默,您所说的一切将会作为呈堂证供!
    #error 停止交易,有内鬼!
}

如图4.所示,#warning 会导致出现警告提示,但仍会继续编译过程。但 #error 除了会出现错误提示外,还会导致编译失败,或者称 build 错误,修复后才能继续。

#line

在生成的代码中,#line指令非常有用。当编译器生成错误或警告时,它通常会声明问题发生的位置,提供文件名、行号和该行内的偏移量。但是,如果问题代码是使用其他文件作为输入自动生成的,并且其他文件包含问题的根本原因,那么在输入文件中报告错误可能比在生成的文件中报告错误更有用。一个#line指令可以指示c#编译器就像错误发生在指定的行号上一样,也可以选择像错误发生在一个完全不同的文件中一样。例5.4 展示了如何使用它。指令后的错误将被报告,好像它来自一个名为footbar.cs的文件的第999行。

static void Main(string[] args)
{
    Inttt x;
    #line 999 "footbar.cs"
    Inttt x;
}

如图5.所示,虽然 Program.cs 的第9行、第11行出现两处明显的语法错误。但提示出现的文件及所在位置却明显不同。请特别关注橙色箭头与白色箭头所示的区别。

另外,文件名部分是可选的,行号也可以伪造,一切都只是注释。您可以通过编写#line default来告诉编译器恢复报告正常的警告和错误状态,否则后面出现的一切错误都会以这个基础继续。

#pragma

#pragma 指令提供了两个特性:它可以用来禁用选定的编译器警告,还可以用来覆盖编译器放入它生成的包含调试信息的 .pdb 文件中的校验和值。这两种方法主要是为代码生成场景设计的,不过它们有时也可以用于禁用普通代码中的警告。例5.5展示了如何使用 #pragma 来防止您声明但没有继续使用的变量而弹出的警告信息。

static void Main(string[] args)
{
    int x;
    #pragma warning disable CS0168
    int y;
}

如图6.所示,在启用 #pragma 指令前,会提示警告变量x未使用。但在启用后,变量y的警告提示未显示。

通常应该避免禁用警告。此特性在生成的代码中非常有用,因为代码生成通常会创建不经常使用的项,而pragmas可能提供了获得干净编译的唯一方法。但是当您手工编写代码时,通常应该能够首先避免警告。

总的来说,如果不是强迫症患者,请勿使用该功能。当然,#pragmas 还有一些其他的能力,比如说为 C# 8.0 中添加的新特性 nullable 等。但对于初学者来说,好像暂时无所谓……但毕竟课题是 C# 8.0 教程,所以我们不得不说一些关于 8.0 的新知识。如下:

#nullable

C# 8.0添加了一个新的指令 #nullable,它允许对可空的注释上下文进行精细控制。这是之后章节中描述的可空引用特性的一部分。(这与之前 #pragmas 中描述的 nullable 警告控件没有重叠,因为我们控制是否启用了nullability注释,与是否启用了与这些注释关联的警告无关)

#region and #endregion

最后,我们有两个不做任何事情的预处理指令。如果你写了#region指令,编译器做的唯一一件事就是确保它们有或者响应#endregion指令。不匹配会导致编译器错误,但是编译器会忽略正确配对的#region和#endregion指令。区域可以嵌套。

这些指令的存在完全是为了便于选择识别它们的文本编辑器。Visual Studio 或 Visual Studio Code 等 C#编辑器使用这组指令可将其包含的代码部分折叠为屏幕上的一行。c#编辑器自动允许扩展和折叠某些特性,比如类定义、方法和代码块(称为outline的特性)。如果您使用这两个指令定义区域,它还将允许扩展和折叠这些区域。

如果将鼠标悬停在折叠区域上,Visual Studio Code 等多数C#编辑器将显示工具提示,显示该区域的内容。

如图7.所示,因为增加了一组 #region 指令,则会在行号后面自动增加出 折叠按钮 (红色箭头所示),会将从 #region 开始,到 #endregion 结束的代码块折叠起来。

虽然代码块 { } 符号也可实现折叠效果,但区别在于,编译器会完全忽略 #region,但 { } 对于编译器来说是有意义的,所以不是完全等同。

本课小结

本课所提到预编译指令,不能给我们的程序带来更多的功能,也无法提高代码执行效率。更多是为代码编辑者使用。大家了解即可,未来读程序时肯定会遇到,可以再来细读。

下节开始数据类型……

相关推荐

快递查询教程,批量查询物流,一键管理快递

作为商家,每天需要查询许许多多的快递单号,面对不同的快递公司,有没有简单一点的物流查询方法呢?小编的回答当然是有的,下面随小编一起来试试这个新技巧。需要哪些工具?安装一个快递批量查询高手快递单号怎么快...

一键自动查询所有快递的物流信息 支持圆通、韵达等多家快递

对于各位商家来说拥有一个好的快递软件,能够有效的提高自己的工作效率,在管理快递单号的时候都需要对单号进行表格整理,那怎么样能够快速的查询所有单号信息,并自动生成表格呢?1、其实方法很简单,我们不需要一...

快递查询单号查询,怎么查物流到哪了

输入单号怎么查快递到哪里去了呢?今天小编给大家分享一个新的技巧,它支持多家快递,一次能查询多个单号物流,还可对查询到的物流进行分析、筛选以及导出,下面一起来试试。需要哪些工具?安装一个快递批量查询高手...

3分钟查询物流,教你一键批量查询全部物流信息

很多朋友在问,如何在短时间内把单号的物流信息查询出来,查询完成后筛选已签收件、筛选未签收件,今天小编就分享一款物流查询神器,感兴趣的朋友接着往下看。第一步,运行【快递批量查询高手】在主界面中点击【添...

快递单号查询,一次性查询全部物流信息

现在各种快递的查询方式,各有各的好,各有各的劣,总的来说,还是有比较方便的。今天小编就给大家分享一个新的技巧,支持多家快递,一次能查询多个单号的物流,还能对查询到的物流进行分析、筛选以及导出,下面一起...

快递查询工具,批量查询多个快递快递单号的物流状态、签收时间

最近有朋友在问,怎么快速查询单号的物流信息呢?除了官网,还有没有更简单的方法呢?小编的回答当然是有的,下面一起来看看。需要哪些工具?安装一个快递批量查询高手多个京东的快递单号怎么快速查询?进入快递批量...

快递查询软件,自动识别查询快递单号查询方法

当你拥有多个快递单号的时候,该如何快速查询物流信息?比如单号没有快递公司时,又该如何自动识别再去查询呢?不知道如何操作的宝贝们,下面随小编一起来试试。需要哪些工具?安装一个快递批量查询高手快递单号若干...

教你怎样查询快递查询单号并保存物流信息

商家发货,快递揽收后,一般会直接手动复制到官网上一个个查询物流,那么久而久之,就会觉得查询变得特别繁琐,今天小编给大家分享一个新的技巧,下面一起来试试。教程之前,我们来预览一下用快递批量查询高手...

简单几步骤查询所有快递物流信息

在高峰期订单量大的时候,可能需要一双手当十双手去查询快递物流,但是由于逐一去查询,效率极低,追踪困难。那么今天小编给大家分享一个新的技巧,一次能查询多个快递单号的物流,下面一起来学习一下,希望能给大家...

物流单号查询,如何查询快递信息,按最后更新时间搜索需要的单号

最近有很多朋友在问,如何通过快递单号查询物流信息,并按最后更新时间搜索出需要的单号呢?下面随小编一起来试试吧。需要哪些工具?安装一个快递批量查询高手快递单号若干怎么快速查询?运行【快递批量查询高手】...

连续保存新单号功能解析,导入单号查询并自动识别批量查快递信息

快递查询已经成为我们日常生活中不可或缺的一部分。然而,面对海量的快递单号,如何高效、准确地查询每一个快递的物流信息,成为了许多人头疼的问题。幸运的是,随着科技的进步,一款名为“快递批量查询高手”的软件...

快递查询教程,快递单号查询,筛选更新量为1的单号

最近有很多朋友在问,怎么快速查询快递单号的物流,并筛选出更新量为1的单号呢?今天小编给大家分享一个新方法,一起来试试吧。需要哪些工具?安装一个快递批量查询高手多个快递单号怎么快速查询?运行【快递批量查...

掌握批量查询快递动态的技巧,一键查找无信息记录的两种方法解析

在快节奏的商业环境中,高效的物流查询是确保业务顺畅运行的关键。作为快递查询达人,我深知时间的宝贵,因此,今天我将向大家介绍一款强大的工具——快递批量查询高手软件。这款软件能够帮助你批量查询快递动态,一...

从复杂到简单的单号查询,一键清除单号中的符号并批量查快递信息

在繁忙的商务与日常生活中,快递查询已成为不可或缺的一环。然而,面对海量的单号,逐一查询不仅耗时费力,还容易出错。现在,有了快递批量查询高手软件,一切变得简单明了。只需一键,即可搞定单号查询,一键处理单...

物流单号查询,在哪里查询快递

如果在快递单号多的情况,你还在一个个复制粘贴到官网上手动查询,是一件非常麻烦的事情。于是乎今天小编给大家分享一个新的技巧,下面一起来试试。需要哪些工具?安装一个快递批量查询高手快递单号怎么快速查询?...

取消回复欢迎 发表评论: