编程技术是改变世界的力量。
本站
当前位置:网站首页 > 后端语言 > 正文

2.1.5 C#8.0教程 - 预处理指令(c#预处理指令作用)

gowuye 2024-04-25 04:45 10 浏览 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,但 { } 对于编译器来说是有意义的,所以不是完全等同。

本课小结

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

下节开始数据类型……

相关推荐

Nginx 响应提速10倍,你需要知道的缓存性能优化——FastCGI调优
Nginx 响应提速10倍,你需要知道的缓存性能优化——FastCGI调优

Nginx缓存优化是帮助大家提升网站性能的重要操作之一,proxy_cache主要用于反向代理时,对后端内容源服务器进行缓存;fastcgi_cache主要用于...

2024-05-20 14:44 gowuye

王者荣耀天魔缭乱和逐梦之音返场活动地址 3月22日开启返场活动
王者荣耀天魔缭乱和逐梦之音返场活动地址 3月22日开启返场活动

王者荣耀官方终于确定了天魔缭乱和逐梦之音的返场活动,这让不少小伙伴乐开了花,返场活动将会在3月22日开启,下面就带来王者荣耀天魔缭乱和逐梦之音返场活动地址!王者...

2024-05-20 14:44 gowuye

常见的嵌入式web服务器有哪些?

嵌入式WEB服务器常见的有:Lighttpd,Shttpd,Thttpd,Boa,Mini_httpd,Appweb,Goahead。Lighttpd地址:http://www.light...

简述几款常见的嵌入式web服务器
简述几款常见的嵌入式web服务器

嵌入式web服务器,是web服务器当中的一种,是基于嵌入式系统而实现的web服务器。指的是在嵌入式系统(通俗点就是单片机系统)上实现的一个web服务器,可以通过...

2024-05-20 14:44 gowuye

教你如何利用fastcgi_cache缓存加速WordPress

在使用nginx缓存之前,必须在nginx里面加载专门的模块,这个模块叫做ngx_cache_purge。添加ngx_cache_purge模块下载ngx_cache_purge模块ngx_cache...

扫描WordPress漏洞

检测已知漏洞WPScan是一款广泛使用的WordPress安全扫描工具,它的一项重要功能是检测已知漏洞。在这篇文章中,我们将深入探讨WPScan如何检测已知漏洞,并结合实际示例,帮助读者更好地理解和应...

消灭 Bug!推荐几个给力的开源 Bug 跟踪工具
消灭 Bug!推荐几个给力的开源 Bug 跟踪工具

在这个充满bug的世界里,最遥远的距离不是生与死,而是你亲手制造的bug就在你眼前,你却怎么都找不到它。因此本文准备了7款优秀的开源bug跟踪系...

2024-05-20 14:43 gowuye

生物信息分析入门全攻略

生物信息学是生命科学研究的重大前沿领域,未来将占据生命科学研究的半壁江山。已经有越来越多的小伙伴投入到生物信息的学习中,但是入门难、深入慢、摸不到方向等都成为持续学习的拦路虎。本文根据生物信息技术大牛...

elkb实践经验,再赠送一套复杂的配置文件
elkb实践经验,再赠送一套复杂的配置文件

原创:小姐姐味道(微信公众号ID:xjjdog),欢迎分享,转载请保留出处。宝剑锋从磨砺出,梅花香自苦寒来。诗人白居易,三月下江南,看到沿路开放的桃花,心潮澎湃...

2024-05-20 14:43 gowuye

超详细从0到1 搭建ELK监控
超详细从0到1 搭建ELK监控

监控分类?Metrics用于记录可聚合的数据。例如,1、队列的当前深度可被定义为一个度量值,在元素入队或出队时被更新;HTTP请求个数可被定义为一个计数器,...

2024-05-20 14:42 gowuye

嵌入式开发 之Web配置页面开发
嵌入式开发 之Web配置页面开发

1.PHP是最好的语言??开发动态页面首选的语言是PHP,村村不能在这里忽悠人,如果你的硬件性能允许切略懂PHP,看到这里就可以退出了。本文面向的受众是Linu...

2024-05-20 14:42 gowuye

Python开发一个网站目录扫描工具用来检测网站是否有漏洞?
Python开发一个网站目录扫描工具用来检测网站是否有漏洞?

开发一个网站目录扫描工具是用来检测网站是否有非法目录请求的一个常见需求之一,我们要通过这个扫描工具来找到通过某个域名可以访问到的网站路径,可能对于有些系统来讲,...

2024-05-20 14:42 gowuye

创建一个类似Youtube的Id——使用PHP/Python/JS/Java/SQL

id通常都是用数字,不巧的是只有10个数字来使用,所以如果你有很多的记录,id往往变得非常冗长。当然对于计算机来说无所谓,但我们更希望id尽可能短。所以我们如何能使id变短?我们可以利用字母让它们附加...

快速云:有助于移动应用安全开发的五条妙计
快速云:有助于移动应用安全开发的五条妙计

许多企业不断地向其开发团队提供培训。但是某些漏洞,如早在十多年前就发现的SQL注入,如今仍广泛存在于各种应用中。因而,安全培训永不过时。在开发移动应用时,开发者...

2024-05-20 14:41 gowuye

洛杉矶国际电影节最佳动画短片奖影片《G’DAY》正式全网上映
洛杉矶国际电影节最佳动画短片奖影片《G’DAY》正式全网上映

7月2日,由M&CSaatchi创作,由深受好评的澳大利亚导演迈克尔·格雷西执导的动画短片《G’day》,正式在全网上映。该影片因其出色的创意赢得了洛...

2024-05-20 14:41 gowuye

取消回复欢迎 发表评论: