《Effective C#》读书笔记——条目4:使用Conditional特性而不是#if条件编译<C#语言习惯>

简介:

  #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 #endif
11             return null;
12         }
复制代码

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

复制代码
1         public void Func()
2         {
3             string msg = null;
4 
5 #if DEBUG
6             msg = "Debug";
7 #endif
8             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特性让我们可以更好地将条件性代码分离开来。

 

阅读书目:《Effective C#》

本文转自gyzhao博客园博客,原文链接:http://www.cnblogs.com/IPrograming/archive/2012/08/21/Effective_CSharp_04.html ,如需转载请自行联系原作者
相关文章
C#学习相关系列之数据类型类的三大特性(二)
C#学习相关系列之数据类型类的三大特性(二)
129 1
|
编译器 C# 开发者
C# 11.0中的新特性:覆盖默认接口方法
C# 11.0进一步增强了接口的灵活性,引入了覆盖默认接口方法的能力。这一新特性允许类在实现接口时,不仅可以提供接口中未实现的方法的具体实现,还可以覆盖接口中定义的默认方法实现。本文将详细介绍C# 11.0中接口默认方法覆盖的工作原理、使用场景及其对现有代码的影响,帮助开发者更好地理解和应用这一新功能。
|
编译器 C# 开发者
C# 9.0中的顶级语句:简化程序入口的新特性
【1月更文挑战第13天】本文介绍了C# 9.0中引入的顶级语句(Top-level statements)特性,该特性允许开发者在不使用传统的类和方法结构的情况下编写简洁的程序入口代码。文章详细阐述了顶级语句的语法、使用场景以及与传统程序结构的区别,并通过示例代码展示了其在实际应用中的便捷性。
|
10月前
|
编译器 C# 开发者
C# 9.0 新特性解析
C# 9.0 是微软在2020年11月随.NET 5.0发布的重大更新,带来了一系列新特性和改进,如记录类型、初始化器增强、顶级语句、模式匹配增强、目标类型的新表达式、属性模式和空值处理操作符等,旨在提升开发效率和代码可读性。本文将详细介绍这些新特性,并提供代码示例和常见问题解答。
233 7
C# 9.0 新特性解析
|
12月前
|
编译器 C# Android开发
震惊!Uno Platform 与 C# 最新特性的完美融合,你不可不知的跨平台开发秘籍!
Uno Platform 是一个强大的跨平台应用开发框架,支持 Windows、macOS、iOS、Android 和 WebAssembly,采用 C# 和 XAML 进行编程。C# 作为其核心语言,持续推出新特性,如可空引用类型、异步流、记录类型和顶级语句等,极大地提升了开发效率。要在 Uno Platform 中使用最新 C# 特性,需确保开发环境支持相应版本,并正确配置编译器选项。通过示例展示了如何在 Uno Platform 中应用可空引用类型、异步流、记录类型及顶级语句等功能,帮助开发者更好地构建高效、优质的跨平台应用。
484 59
|
10月前
|
C# 开发者
C# 10.0 新特性解析
C# 10.0 在性能、可读性和开发效率方面进行了多项增强。本文介绍了文件范围的命名空间、记录结构体、只读结构体、局部函数的递归优化、改进的模式匹配和 lambda 表达式等新特性,并通过代码示例帮助理解这些特性。
179 2
|
11月前
|
JSON C# 开发者
C#语言新特性深度剖析:提升你的.NET开发效率
【10月更文挑战第15天】C#语言凭借其强大的功能和易用性深受开发者喜爱。随着.NET平台的演进,C#不断引入新特性,如C# 7.0的模式匹配和C# 8.0的异步流,显著提升了开发效率和代码可维护性。本文将深入探讨这些新特性,助力开发者在.NET开发中更高效地利用它们。
149 1
|
开发框架 .NET 编译器
总结一下 C# 如何自定义特性 Attribute 并进行应用
总结一下 C# 如何自定义特性 Attribute 并进行应用
304 1
|
开发框架 .NET Java
ASP.NET Core高级编程--C#基本特性(一)
本文章简略介绍C#的部分特性
c#之Attribute特性的原理
c#之Attribute特性的原理
186 0