C#-#define条件编译
本文导读:
C#的预处理器指令从来不会转化为可执行代码的命令,但是会影响编译过程的各个方面,常用的预处理器指令有#define、#undef、#if,#elif,#else和#endif等等,下面介绍C#中使用#define进行条件编译的实例。
C#中条件编译指令用于按条件包含或排除源文件中的某些部分。在Visual Studio中,会看到被排除的代码显示为灰色。
一、#define可以用来做什么
1、当计划发布两个版本的代码的时候。即基本版和拥有更多版本的企业版,就可以用到条件编译指令;
2、例如同一个文件给silverlight、wpf、winform等使用,并且还考虑Debug和Release等,有大部分代码是一样的;
3、指定函数和属性是否编译到最终产品中去。
二、#define用法
语法:#define 名称
注意:这里名称取Debug,你也可以取其他名称如Dragon
#define Debug
说明:
1、Debug可以看做是声明的一个变量,但此变量没有真正的值,存在时#if Debug结果为true,否则为false;
2、#define单独用没什么意义,一般是和#if或者Conditional特性结合使用;
3、#define必须定义在所有using命名空间前面;
4、Debug与DEBUG是不同的,C#区分大小写。
三、#define条件编译实例
方式一、使用#if
#define Dragon
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics; namespace ConditionalCompilation
{
class Program
{
static void Main(string[] args)
{
#if Dragon
Console.WriteLine("Dragon is defined");
#else
Console.WriteLine("Dragon is not defined");
#endif
Console.ReadKey();
}
}
}
输出结果如下:

如果注释掉 //#define Dragon ,输出结果为:

方式二、使用Conditional特性
我们可以将一些函数隔离出来,使得它们只有在定义了某些环境变量或者设置了某个值之后才能发挥作用,使用Conditional特性的隔离策略要比#if/#endif不容易出错。
#define Debug
#define Trace
#if (Debug && Trace)
#define DebugAndTrace
#endif
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics; namespace ConditionalCompilation
{
class Program
{
static void Main(string[] args)
{
Print0();
Print1();
Print2();
Print3();
Console.ReadKey();
} [Conditional("DEBUG")]
static void Print0()
{
Console.WriteLine("DEBUG is defined");
} [Conditional("Debug")]
static void Print1()
{
Console.WriteLine("Debug is defined");
} //定义了Debug或者Trace后才会执行此方法
//或者的关系
[Conditional("Debug"), Conditional("Trace")]
static void Print2()
{
Console.WriteLine("Debug or Trace is defined");
} //只有定义了Debug和Trace后才会执行此方法
//并且的关系
[Conditional("DebugAndTrace")]
static void Print3()
{
Console.WriteLine("Debug and Trace is defined");
}
}
}
输出结果如下:

说明:
1、代码中没有定义DEBUG,却输出了DEBUG,是因为DEBUG版本,自动定义了DEBUG。“项目——右键——属性——生成选项卡——常规栏”下的定义 DEBUG 常量(U)前面的复选框被选中。当然你可以去掉其选中状态,这样就不会输出DEBUG了。
2、如果Debug和Trace均没有定义,则不会输出Debug or Trace;只有Debug和Trace均定义了,才会输出Debug and Trace。
3、可以给Conditional增加多个属性如示例代码 [Conditional("Debug"), Conditional("Trace")] ,不过多个属性之间的关系是或的关系,即“Debug”或者“Trace”任意一个被定义了,那么对应方法就会被执行。
4、如果需要增加多个与的属性,直接用Conditional是无法实现的,需要借助#if/#endif间接来完成,如示例代码中的组合操作
#if (Debug && Trace)
#define DebugAndTrace
#endif
使用Conditional属性的方法受到以下限制:
1、条件方法必须是类声明或结构声明中的方法。如果在接口声明中的方法上指定Conditional属性,将出现编译时错误;
2、条件方法不能是接口方法的实现。否则将发生编译时错误;
3、条件方法必须具有void返回类型;
4、不能用override修饰符标记条件方法。但是,可以用virtual修饰符标记条件方法。此类方法的重写方法隐含为有条件的方法,而且不能用Conditional属性显式标记。
环境变量(或条件编译符号)的设置方法有三:
1)用#define定义以及#undef取消定义,在所有using命名空间前面定义;
2)用编译器命令行选项(例如,/define:DEBUG),在“项目——右键——属性——生成选项卡——常规栏”下的条件编译符号(Y)中设置(如果多个,可以用英文逗号隔开)。DEBUG版本下,系统默认设置了DEBUG和TRACE;
3)用操作系统外壳程序中的环境变量(例如,set DEBUG=1)。
参考链接①:http://www.studyofnet.com/news/1240.html
参考链接②:http://blog.csdn.net/teng_s2000/article/details/5510420
参考链接③:https://msdn.microsoft.com/zh-cn/library/system.diagnostics.conditionalattribute.aspx
C#-#define条件编译的更多相关文章
- C/C++预处理指令#define,条件编译#ifdefine
本文主要记录了C/C++预处理指令,常见的预处理指令如下: #空指令,无任何效果 #include包含一个源代码文件 #define定义宏 #undef取消已定义的宏 #if如果给定条件为真,则编译下 ...
- C# 条件编译
本文导读: C#的预处理器指令从来不会转化为可执行代码的命令,但是会影响编译过程的各个方面,常用的预处理器指令有#define.#undef.#if,#elif,#else和#endif等等,下面介绍 ...
- c/c++ define用法
define,无参宏定义的一般形式为:#define 标识符 字符串 外文名 define 词条范围 计算机专业用语 无参一般形式 #define 标识符 字符串 带参一般形式 #define 宏名( ...
- define和const的一点点小知识
define篇 1.#define 的作用 在C或C++语言源程序中允许用一个标识符来表示一个字符串,称为“宏”. 被定义为“宏”的标识符称为“宏名”. 在编译预处理时,对程序中所有出现的“宏名”,都 ...
- #define用法详解
1.#define 的作用 在C或C++语言源程序中允许用一个标识符来表示一个字符串,称为“宏”.被定义为“宏”的标识符称为“宏名”.在编译预处理时,对程序中所有出现的“宏名”,都用宏定义中的字符串去 ...
- 【转】 #define用法详解
#define用法详解 1.#define 的作用 在C或C++语言源程序中允许用一个标识符来表示一个字符串,称为“宏”.被定义为“宏”的标识符称为“宏名”.在编译预处理时,对程序中所有出现的“宏 ...
- #define的3种用法详解
1.#define 的作用 在C或C++语言源程序中允许用一个标识符来表示一个字符串,称为"宏".被定义为"宏"的标识符称为"宏名".在编译 ...
- C#创建、安装、卸载、调试Windows Service(Windows 服务)的简单教程
前言:Microsoft Windows 服务能够创建在它们自己的 Windows 会话中可长时间运行的可执行应用程序.这些服务可以在计算机启动时自动启动,可以暂停和重新启动而且不显示任何用户界面.这 ...
- C和指针 第十四章 预处理器 头文件
编写一个C程序,第一个步骤称为预处理,预处理在代码编译之前,进行一些文本性质的操作,删除注释.插入被include的文件.定义替换由#define定义的符号,以及确定代码的部分内容是否应该按照条件编译 ...
随机推荐
- NET Core-学习笔记(三)
这里将要和大家分享的是学习总结第三篇:首先感慨一下这周跟随netcore官网学习是遇到的一些问题: a.官网的英文版教程使用的部分nuget包和我当时安装的最新包版本不一致,所以没法按照教材上给出的列 ...
- 【开源】.Net Api开放接口文档网站
开源地址:http://git.oschina.net/chejiangyi/ApiView 开源QQ群: .net 开源基础服务 238543768 ApiView .net api的接口文档查看 ...
- .Net Core上也可以使用的二维码组件
我Fork了QRCoder,并且兼容了.Net Core,图形库用的是ZKWeb.System.Drawing Github: https://github.com/zkweb-framework/Q ...
- Unity3D框架插件uFrame实践记录(一)
1.概览 uFrame是提供给Unity3D开发者使用的一个框架插件,它本身模仿了MVVM这种架构模式(事实上并不包含Model部分,且多出了Controller部分).因为用于Unity3D,所以它 ...
- ASP.NET Core 中文文档 第四章 MVC(4.3)过滤器
原文:Filters 作者:Steve Smith 翻译:刘怡(AlexLEWIS) 校对:何镇汐 ASP.NET MVC 过滤器 可在执行管道的前后特定阶段执行代码.过滤器可以配置为全局有效.仅对控 ...
- WPF 捕获键盘输入事件
最近修改的一个需求要求捕获键盘输入的 Text,包括各种标点符号. 最开始想到的是 PreviewKeyDown 或者 PreviewKeyUp 这样的键盘事件. 但是这两个事件的对象 KeyEven ...
- 使用四元数解决万向节锁(Gimbal Lock)问题
问题 使用四元数可以解决万向节锁的问题,但是我在实际使用中出现问题:我设计了一个程序,显示一个三维物体,用户可以输入绕zyx三个轴进行旋转的指令,物体进行相应的转动. 由于用户输入的是绕三个轴旋转的角 ...
- Linux.NET学习手记(6)
各位读者大家好,好长一段时间没有更新文章了,自从参加工作之后,每天等待去做的工作没完没了,个人的时间也变得奢侈起来,今后要尽量从中脱身,抽更多的时间来完成自己想做的事情(希望如此). 言归正传,上一回 ...
- 《徐徐道来话Java》(1):泛型的基本概念
泛型是一种编程范式(Programming Paradigm),是为了效率和重用性产生的.由Alexander Stepanov(C++标准库主要设计师)和David Musser(伦斯勒理工学院CS ...
- Linux1 在Linux(CentOS)上安装MySql详细记录
前记: 毕业两年了,前两天换了份工作,由以前的传统行业跳到了互联网行业.之前的公司一直在用WinServer2003+Tomcat+SqlServer/Oracle这套部署环境.对于Linux+To ...