Effective C# Item 4: Use Conditional Attributes Instead of #if
2006-09-07 10:59
549 查看
Item 4: Use Conditional Attributes Instead of #if
我们可以使用#if/#endif从同一源码中生成不同的程序版本,比如debug和release版本,不过它并没有那么好用。#if/#endif很容易造成混乱,代码也难以阅读和调试。开发语言的设计者们意识到这个问题,并且为不同的开发环境创建了更好的生成工具。在C#中就添加了Conditional属性,它可以更好的完成工作。conditional属性是在方法级别(method level)上被提供的,因此你必须将不同情况的代码分布到特定的方法中去。我们应当在创建不同版本程序块时使用conditional属性代替#if/#endif。
有经验的程序员使用条件编译来检验对象的事前和事后状态。我们应当使用私有方法来检验这些类和对象。由于是条件编译,它们只会出现在debug版本里。
private void CheckState()
public void Func()
private void CheckState()
public string LastName
[Conditional("DEBUG")]
private void CheckState()
public string LastName
public string LastName
[Conditional("DEBUG"),Conditional("TRACE")]
private void CheckState()
当我们想要使用and进行条件判断时,就必须在代码中提前添加判断
#if (VAR1 && VAR2)
#define BOTH
#endif
如果想要创建基于多个环境变量之间and关系的方法,我们就要回头使用#if,但是我们并没有创建任何可执行程序在代码块中。
Conditional属性只能应用在整个方法上。另外,应用Conditional属性的方法必须是void型。我们不能将Conditional添加到一个程序块或者有返回值的方法上。因此,我们需要谨慎的构建方法并将条件判断行为隔离出来。使用这种方法时我们必须要仔细检查是否会对程序产生负作用,但是同#if/#endif相比,Conditional属性要强很多,至少不会因为使用#if/#endif而错误删除重要的程序块。
上面的所有例子中我们都使用的DEBUG和TRACE符号。我们可以自定义任何符号,Conditional属性支持多种符号定义方式,我们可以通过编译器命令行,操作系统环境变量或者代码中定义它们。
Conditional属性会生成比#if/#endif更高效的中间语言。它只能应用在函数级别,这使得我们必须构建更好的代码结构。通过使用Conditional可以帮助我们避免在使用#if/#endif时会发生的错误。Conditional属性为我们隔离条件代码提供了更加清晰的方式。
译自 Effective C#:50 Specific Ways to Improve Your C# Bill Wagner著
P.S.
关于多个Conditional之间AND的关系 ,在MSDN中是这样写的:
[Conditional("A")] public static void IfAandB( )
[Conditional("B")] static void AandBPrivate( )
条件方法不能为接口声明方法和接口实现方法。
不能使用override来修饰条件方法,但是可以将其声明为virtual型。被override的virtual型条件方法的方法隐含有条件方法属性,不能对其使用Conditional属性。重写条件方法很容易造成混乱。如果条件方法用在委托创建表达式中时,也会发生错误。
class Class1
class Class2: Class1
{
public override void M() {
Console.WriteLine("Class2.M executed");
base.M(); //由于DEBUG未定义,base.M()不被调用
}
}
回到目录
我们可以使用#if/#endif从同一源码中生成不同的程序版本,比如debug和release版本,不过它并没有那么好用。#if/#endif很容易造成混乱,代码也难以阅读和调试。开发语言的设计者们意识到这个问题,并且为不同的开发环境创建了更好的生成工具。在C#中就添加了Conditional属性,它可以更好的完成工作。conditional属性是在方法级别(method level)上被提供的,因此你必须将不同情况的代码分布到特定的方法中去。我们应当在创建不同版本程序块时使用conditional属性代替#if/#endif。
有经验的程序员使用条件编译来检验对象的事前和事后状态。我们应当使用私有方法来检验这些类和对象。由于是条件编译,它们只会出现在debug版本里。
private void CheckState()
public void Func()
private void CheckState()
public string LastName
[Conditional("DEBUG")]
private void CheckState()
public string LastName
public string LastName
[Conditional("DEBUG"),Conditional("TRACE")]
private void CheckState()
当我们想要使用and进行条件判断时,就必须在代码中提前添加判断
#if (VAR1 && VAR2)
#define BOTH
#endif
如果想要创建基于多个环境变量之间and关系的方法,我们就要回头使用#if,但是我们并没有创建任何可执行程序在代码块中。
Conditional属性只能应用在整个方法上。另外,应用Conditional属性的方法必须是void型。我们不能将Conditional添加到一个程序块或者有返回值的方法上。因此,我们需要谨慎的构建方法并将条件判断行为隔离出来。使用这种方法时我们必须要仔细检查是否会对程序产生负作用,但是同#if/#endif相比,Conditional属性要强很多,至少不会因为使用#if/#endif而错误删除重要的程序块。
上面的所有例子中我们都使用的DEBUG和TRACE符号。我们可以自定义任何符号,Conditional属性支持多种符号定义方式,我们可以通过编译器命令行,操作系统环境变量或者代码中定义它们。
Conditional属性会生成比#if/#endif更高效的中间语言。它只能应用在函数级别,这使得我们必须构建更好的代码结构。通过使用Conditional可以帮助我们避免在使用#if/#endif时会发生的错误。Conditional属性为我们隔离条件代码提供了更加清晰的方式。
译自 Effective C#:50 Specific Ways to Improve Your C# Bill Wagner著
P.S.
关于多个Conditional之间AND的关系 ,在MSDN中是这样写的:
[Conditional("A")] public static void IfAandB( )
[Conditional("B")] static void AandBPrivate( )
条件方法不能为接口声明方法和接口实现方法。
不能使用override来修饰条件方法,但是可以将其声明为virtual型。被override的virtual型条件方法的方法隐含有条件方法属性,不能对其使用Conditional属性。重写条件方法很容易造成混乱。如果条件方法用在委托创建表达式中时,也会发生错误。
class Class1
class Class2: Class1
{
public override void M() {
Console.WriteLine("Class2.M executed");
base.M(); //由于DEBUG未定义,base.M()不被调用
}
}
回到目录
相关文章推荐
- Item 4:Use Conditional Attributes Instead of #if
- Item 4: Use Conditional Attributes Instead of #if(Effective C#)
- Item 4: Use Conditional Attributes Instead of #if
- Use Conditional Attributes instead of #if - Effective C#学习笔记(4)
- Effective C# 4:use conditional attributes instead of #if
- An effective way to use pattern to instead of multiple if else statements
- c# Use Properties Instead of Accessible Data Members
- When to Use Delegates Instead of Interfaces (C# Programming Guide)
- Effective Java 32 Use EnumSet instead of bit fields
- Effective C# Item 10: Understand the Pitfalls of GetHashCode()
- Item 16: Use the same form in corresponding uses of new and delete.(Effective C++)
- Effective Java - Item 1: Consider static factory methods instead of constructors
- Item 1: Use Properties Instead of Accessible Data Members(Effective C#)
- Item 1: Use Properties Instead of Accessible Data Members
- Effective C# Item 29: Use the new Modifier Only When Base Class Updates Mandate it
- Item 1:Always Use Properties Instead of Accessible Date Members
- Effective Java——Item 1,Consider static factory methods instead of constructors
- Effective C++ Item 16 Use the same form in corresponding uses of new and delete
- Effective C# Item 1: Always Use Properties Instead of Accessible Data Members
- Effective Objective-C 2.0:Item 50: Use NSCache Instead of NSDictionary for Caches