4、尽量使用条件属性(Conditional Attribute)而不是#if/#endif预处理

对于这条规则我们一般关心得比较少,只有在系统调试时用得比较多。
      在讲这条规则之前让我们来了解下“什么是条件属性”。

对于.net初学者,当第一次遇到函数上面加一对“[]”中括弧时,一定觉得很陌生。如下所示:

      [assembly: AssemblyTitle("dd")]

.net框架提供了一个特性:属性(Attribute),注意:此属性非彼属性(property)(这都是翻译惹的祸)。
      .net
框架提供了两种类型的Attribute属性:内置属性,自定义属性。顾名思义,内置属性是框架已经为我们开发好的在语言中置入的属性,自定义属性是用户自行定义、创建的属性。其中条件属性(Conditional Attribute)就是属于内置属性。.net框架提供了数百个预先定义好的内置属性,这就不多说了。下面简单的说一下怎么创建用户自定义属性,从而帮助我们理解什么是Attribute属性。

首先要搞清楚:设计实现自定义属性本质就是设计实现一个自定义的类,这个类除了要满足一般类的要求外还要满足以下几个条件:

1、继承System.Attribute;

2、给该类添加AttributeUsageAttribute属性,限制属性类的用法,通过AttributeUsageAttribute类的AttributeTargets参数来指定属性类可以用于何处。如将属性类用于类、结构或者方法等等。

   举例说明:

创建一个新的属性ClassInfo,记录类的创建时间。

ContractedBlock.gif ExpandedBlockStart.gif Code
 1 [AttributeUsage(AttributeTargets.Class|AttributeTargets.Struct)]
 2     public class ClassInfoAttribute:Attribute
 3     {
 4         private string _createDate;
 5 
 6         public ClassInfoAttribute(string createDate)
 7         {
 8             _createDate = createDate;
 9         }
10 
11         public string createDate
12         {
13             get
14             {
15                 return _createDate;
16             }
17         }
18     }

    测试类:

ContractedBlock.gif ExpandedBlockStart.gif Code
 1 [ClassInfo("2009-08-10")]
 2     public class TClass
 3     {
 4         public string GetAttribute()
 5         {
 6             MemberInfo memInfo = typeof(TClass);
 7             Object[] attributes = memInfo.GetCustomAttributes(
 8                 typeof(ClassInfoAttribute), false);
 9             if (0 != attributes.GetLength(0))
10             {
11                 ClassInfoAttribute item = attributes[0as ClassInfoAttribute;
12                 if (null != item)
13                 {
14                     return item.createDate;
15                 }
16             }
17             return string.Empty;
18         }
19 
20         [Conditional("DEBUG")]
21         public virtual void TestAtDebug()
22         {
23             Console.WriteLine("Test at debuging condition.");
24         }
25 
26         public void Test()
27         {
28             Console.WriteLine("Test at normal condition.");
29         }
30     }

    至此我们应该对Attribute属性大体了解了。下面来看看条件属性(Conditional Attribute)到底是怎么回事。

ContractedBlock.gif ExpandedBlockStart.gif Code
 1 [Conditional("DEBUG")]
 2         public virtual void TestAtDebug()
 3         {
 4             Console.WriteLine("Test at debuging condition.");
 5         }
 6 
 7         public void Test()
 8         {
 9             Console.WriteLine("Test at normal condition.");
10         }

   在debug环境下执行的结果是:

Test at debuging condition.
      Test at normal condition.

    在
release环境下执行的结果是:

Test at normal condition.

条件属性是定义方法的运行环境的。条件属性只能在方法上使用。使用条件属性的方法必须符合以下规则:

1、   该方法必须是某个类中的方法;

2、   该方法不能是override方法,但可以是virtual方法。注意:当该方法是virtual方法时,则在派生类中对应的override方法也具有这个属性;

3、   该方法返回的类型必须是void类型;

4、   该方法不能是接口的实现。

上面讲到条件属性只能在方法上使用,所以你应该用条件属性来修饰在不同条件下使用的方法,只有当你要在不同条件下使用一块代码时才用#if/#endif快修饰,即使这样你也应该将该段代码封装到一个方法中。
    再来看个例子:
 

ContractedBlock.gif ExpandedBlockStart.gif Code
 1 public class Name
 2     {
 3         private string _firstName;
 4         public string FirstName
 5         {
 6             set
 7             {
 8                 CheckName2(value);
 9                 _firstName = value;
10             }
11         }
12 
13         private void CheckName1(string item)
14         {
15             #if DEBUG
16             Debug.Assert(!string.IsNullOrEmpty(item), "Name cannot be empty!");
17             #endif
18         }
19 
20         [Conditional("DEBUG")]
21         private void CheckName2(string item)
22         {
23             if(string.IsNullOrEmpty(item))
24             Console.WriteLine("Name cannot be empty!");
25         }
26 
27     }


    虽然CheckName1和CheckName2的功能一样,但是你肯定会更愿意选择CheckName2方法。

下面是Release编译的程序集被反编译后的结果:

  #if DEBUG/#endif


    
     [Conditional("DEBUG")]


      #if DEBUG/#endif只有在debug环境下才会被编译、执行。当编译器遇到#if语句后,编译器会检查与编译环境相关的符号是否存在,如果存在,就编译#if块中的代码,如果不存在,编译器会忽略之后的代码直到#endif。当采用Conditional属性时,不管DEBUG环境变量是否被定义,Conditional属性修饰的方法总会被编译到程序集中。这或许看上去是低效的,但这只是占用一点硬盘空间,且该方法不会被载入到内存,更不会被编译成机器代码,除非它被调用。这样做的好处是生成更高效的IL(中间语言Intermediate Language)代码,从而增强程序的可伸缩性,唯一不足的是带来了一点微不足道的硬盘空间开销。

另外,如果过多的在程序块中添加#if/#endif块,使#if/#endif块与普通代码混在一起,容易造成程序结构的混乱,晦涩难懂。并且在调试完之后,为了使用户不会被这些调试信息弄糊涂,还需要把这些#if/#endif一个一个的去掉,这样不仅不方便而且容易引发错误。#if/#endif的这些缺点正好是Conditional属性的优点。至于Conditional属性限制方法的返回类型只能是void类型,不适应返回非void类型的方法,如果你一定要这样做,别忘了可以给方法传递out类型的参数。

总之:Conditional属性跟#if/#endif预处理比起来,具有以下几点优势:

1、  可以由定义标记来灵活的控制;

2、 可以生成更高效的IL代码;

3、 帮助你强制在条件代码上使用更好的结构;

4、可以避免因使用#if/#endif而产生的常见的错误;

     5、能更好的区分条件代码和普通代码。

转载于:https://www.cnblogs.com/JiangSoney/archive/2009/08/10/1543197.html

#if, #elseif, and #endif are preprocessor directives commonly used in programming languages such as C, C++, and C#. These directives are used to conditionally compile code based on certain conditions. The #if directive allows you to test a condition and include or exclude code based on the result. It is followed by a condition, which can be a defined constant, a macro expression, or a combination of these. If the condition evaluates to true, the block of code following the #if directive is compiled. Otherwise, it is skipped. The #elseif directive is used to test an additional condition if the preceding #if or #elseif condition(s) evaluated to false. It provides an alternative condition to be checked. If the condition evaluates to true, the block of code following the #elseif directive is compiled. Otherwise, it is skipped. The #endif directive marks the end of a conditional block. It is used to close the block of code associated with the most recent #if or #elseif directive. Here's an example usage of these directives in C: ```c #define DEBUG_MODE #if defined(DEBUG_MODE) printf("Debug mode is enabled.\n"); #elif defined(TEST_MODE) printf("Test mode is enabled.\n"); #else printf("No special mode is enabled.\n"); #endif ``` In this example, if the `DEBUG_MODE` macro is defined, the code within the first block will be compiled and executed. If not, it will check for the `TEST_MODE` macro and execute the code within the second block if it is defined. If neither macro is defined, the code within the else block will be executed.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值