当前位置: 首页 > news >正文

.NET/C# 使用 #if 和 Conditional 特性来按条件编译代码的不同原理和适用场景

有小伙伴看到我有时写了 #if 有时写了 [Conditional] 问我两个不是一样的吗,何必多此一举。然而实际上两者的编译处理是不同的,因此也有不同的应用场景。

于是我写到这篇文章当中。


条件编译符号和预处理符号

我们有时会使用 #if DEBUG 或者 [Conditional("DEBUG")] 来让我们的代码仅在特定的条件下编译。

而这里的 DEBUG 是什么呢?

  • 在我们编写的 C# 代码中,这个叫做 “条件编译符号”(Conditional compilation symbols)
  • 在项目的构建过程中,这个叫做 “定义常量”(Define constants)
  • 而在将 C# 代码编译到 dll 的编译环节,这个叫做 “预处理符号”(Preprocessor symbols)

本文要讨论的是 #ifConditional 的使用,这是在 C# 代码中的使用场景,因此,本文后面都将其称之为 “条件编译符号”。

区别

#if

#if DEBUG

Console.WriteLine("欢迎来 blog.walterlv.com 来做客呀!");

#endif

在这段代码中,#if DEBUG#endif 之间的代码仅在 DEBUG 下会编译,在其他配置下是不会编译的。

Conditional

[Conditional("DEBUG")]
public void Foo()
{
    Console.WriteLine("欢迎来 blog.walterlv.com 来做客呀!");
}

而这段代码,是会被编译到目标程序集中的。它影响的,是调用这个方法的代码。调用这个方法的代码,仅在 DEBUG 下会编译,在其他配置下是不会编译的。

场景

因为 #if DEBUG#endif 仅仅影响包含在其内的代码块,因此其仅仅影响写的这点代码所在的项目(或者说程序集)。于是使用 #if 只会影响实现代码。

[Conditional("DEBUG")] 影响的是调用它的代码,因此可以设计作为 API 使用——让目标项目(或者程序集)仅在目标项目特定的配置下才会编译。


我的博客会首发于 https://blog.walterlv.com/,而 CSDN 会从其中精选发布,但是一旦发布了就很少更新。

如果在博客看到有任何不懂的内容,欢迎交流。我搭建了 dotnet 职业技术学院 欢迎大家加入。

知识共享许可协议

本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。欢迎转载、使用、重新发布,但务必保留文章署名吕毅(包含链接:https://walterlv.blog.csdn.net/),不得用于商业目的,基于本文修改后的作品务必以相同的许可发布。如有任何疑问,请与我联系。

相关文章:

  • 使用 Roslyn 分析代码注释,给 TODO 类型的注释添加负责人、截止日期和 issue 链接跟踪
  • 为 NuGet 指定检测的 MSBuild 路径或版本,解决 MSBuild auto-detection: using msbuild version 自动查找路径不合适的问题
  • 解决方案文件 sln 中的项目类型 GUID
  • 两种方法设置 .NET/C# 项目的编译顺序,而不影响项目之间的引用
  • 理解 Visual Studio 解决方案文件格式(.sln)
  • nuget.exe 还原解决方案 NuGet 包的时候出现错误:调用的目标发生了异常。Error parsing the nested project section in solution file
  • 找出 .NET Core SDK 是否使用预览版的全局配置文件在哪里(探索篇)
  • 如何在 Visual Studio 2019 中设置使用 .NET Core SDK 的预览版(全局生效)
  • 使用基于 Roslyn 的 Microsoft.CodeAnalysis.PublicApiAnalyzers 来追踪项目的 API 改动,帮助保持库的 API 兼容性
  • Visual Studio 2019 中使用 .NET Core 预览版 SDK 的全局配置文件在哪里?
  • 推荐几款连字字体,在代码编辑器中启用连字字体(Visual Studio Code)
  • 找回你 C 盘丢失的空间(SpaceSniffer)
  • System.InvalidOperationException:“寄宿 HWND 必须是子窗口。”
  • 通过 AppSwitch 禁用 WPF 内置的触摸让 WPF 程序可以处理 Windows 触摸消息
  • 如何为非常不确定的行为(如并发)设计安全的 API,使用这些 API 时如何确保安全
  • 【407天】跃迁之路——程序员高效学习方法论探索系列(实验阶段164-2018.03.19)...
  • JavaScript服务器推送技术之 WebSocket
  • React的组件模式
  • SpringCloud集成分布式事务LCN (一)
  • Vim 折腾记
  • 成为一名优秀的Developer的书单
  • 开源地图数据可视化库——mapnik
  • 数组大概知多少
  • 推荐一个React的管理后台框架
  • 想使用 MongoDB ,你应该了解这8个方面!
  • 一个完整Java Web项目背后的密码
  • 应用生命周期终极 DevOps 工具包
  • 运行时添加log4j2的appender
  • 7行Python代码的人脸识别
  • #LLM入门|Prompt#3.3_存储_Memory
  • #pragma once
  • (Git) gitignore基础使用
  • (js)循环条件满足时终止循环
  • (JSP)EL——优化登录界面,获取对象,获取数据
  • (LeetCode C++)盛最多水的容器
  • (十一)JAVA springboot ssm b2b2c多用户商城系统源码:服务网关Zuul高级篇
  • (四)鸿鹄云架构一服务注册中心
  • (算法)Travel Information Center
  • (转)nsfocus-绿盟科技笔试题目
  • (转载)Google Chrome调试JS
  • ***测试-HTTP方法
  • .net on S60 ---- Net60 1.1发布 支持VS2008以及新的特性
  • .NET/C# 异常处理:写一个空的 try 块代码,而把重要代码写到 finally 中(Constrained Execution Regions)
  • @for /l %i in (1,1,10) do md %i 批处理自动建立目录
  • @拔赤:Web前端开发十日谈
  • @开发者,一文搞懂什么是 C# 计时器!
  • [ CTF ] WriteUp- 2022年第三届“网鼎杯”网络安全大赛(白虎组)
  • [AIGC] SQL中的数据添加和操作:数据类型介绍
  • [AutoSAR系列] 1.3 AutoSar 架构
  • [BZOJ1877][SDOI2009]晨跑[最大流+费用流]
  • [C#基础知识系列]专题十七:深入理解动态类型
  • [C#小技巧]如何捕捉上升沿和下降沿
  • [Codeforces] number theory (R1600) Part.11
  • [Dxperience.8.*]报表预览控件PrintControl设置
  • [EMWIN]FRAMEWIN 与 WINDOW 的使用注意