博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
《Effective C#》读书笔记——条目4:使用Conditional特性而不是#if条件编译<C#语言习惯>...
阅读量:6831 次
发布时间:2019-06-26

本文共 1840 字,大约阅读时间需要 6 分钟。

  #if/#endif 语句常用来基于同一份源码生成不同的编译结果,其中最常见的就是debug版和release版。但是这些工具在实际应用中并不是非常友好,因为它们容易被滥用,其代码页进而难以理解或调试。C#设计中考虑到这个问题,并提供了更好的工具——Conditional特性,用来为不同的环境编译不同的机器码。Conditional特性适用于方法的层面,这将强制我们将条件代码拆分为独立的方法。在需要编写条件代码时,我们应该使用Conditional特性来替代#if/#endif。

 

使用#if/#endif 语句的缺点

  例如编写一个私有方法来获取调用它的函数名称:

1         private string CheckMethod() 2         { 3  4 #if DEBUG 5             Trace.WriteLine("Entering CheckState for Person"); 6  7             string methodName = new StackTrace().GetFrame(1).GetMethod().Name; 8  9             return methodName;10 #endif11             return null;12         }

条件编译#if和#endif将会在最终release版本中留下一个名为CheckMethod()的空方法,但它在release版和debug版中都将被调用,虽然在release版本中CheckMethod()什么也不做,但是方法的加载、JIT编译和调用仍旧有些开销。而且这也容易引入一些问题:

1         public void Func()2         {3             string msg = null;4 5 #if DEBUG6             msg = "Debug";7 #endif8             Console.WriteLine(msg);9         }

这段代码在Debug版本中不会有问题,但是在release版本中就会输出一个空行,出错的原因是因为我们把属于主程序的逻辑和条件编译的逻辑混合在一起了。在源代码中随意使用#if和#endif将让你很难诊断出不同版本之间的差异。

 

更好的解决办法——使用Conditional特性

  为了避免出现上面的问题我们可以使用Conditional特性。使用Conditional特性即可将一些函数拆分出来,让其只有在定义了某些环境变量或者设置了某个值之后才能编译并成为类的一部分。Conditional特性最常用的地方就是讲一段代码变成调试语句。使用Conditional特性的隔离策略要比#if/#endif不容易出错。

看下面的代码:

1          [Conditional("DEBUG")]2         private void CheckMethod()3         {4             Trace.WriteLine("Entering CheckState for Person");5             string methodName = new StackTrace().GetFrame(1).GetMethod().Name;6         }

无论是否定义了DEBUG环境变量,CheckMethod()方法都将被编译到程序集中。但是如果没有被调用,CheckMethod()方法并不会被加载到内存中,也不会被JIT编译。这其实也揭示了C#编译器的编译过程与JIT编译座次之间的区别。

 

Conditional特性的限制

Conditional特性只可以应用在整个方法上。

任何使用了Conditional特性的方法都只能返回void类型。

 

小节:

综上所述,使用Conditional特性生成的IL要比使用#if/#endif时更有效率。同时,将其限制在函数层面上可以更清晰的将条件性代码分离出来,以便进一步保证代码的良好结构。此外C#编译器也为此提供良好的支持,从而避免了以前使用#if/#endif时常犯的错误。与预处理指令相比,Conditional特性让我们可以更好地将条件性代码分离开来。

 

阅读书目:

转载地址:http://fdjkl.baihongyu.com/

你可能感兴趣的文章
Java面试题
查看>>
Android 内存管理基本介绍
查看>>
欧拉函数
查看>>
支持开源,崇尚技术,追求真理,充实人生
查看>>
React—Native开发之 Could not connect to development server(Android)解决方法
查看>>
Android笔记之Snackbar的基本使用
查看>>
将博客搬至CSDN
查看>>
div宽高设置为百分比
查看>>
python multiprocess不能完全关闭socket的验证
查看>>
深入解读ESB与SOA的关系
查看>>
冒泡排序和选择排序
查看>>
Add Auto Login computer by Registy(自动登陆计算机通过增加注册表键值方法)
查看>>
Python 标准库中的装饰器
查看>>
数论12——浅谈指数与对数
查看>>
几种重要的网络演化模型
查看>>
override与重载(overload)的区别
查看>>
maven项目 jsp报错
查看>>
UVA699 dfs and map
查看>>
###20175311MyCP(课下作业,必做)
查看>>
WCF 第二章 契约 同步请求回复操作
查看>>