本文主要講述C#中计螺,使用 #if 和 Conditional 特性來按條件編譯代碼的不同原理和適用場景码俩。
本文參考了c# Conditional用法詳解和.NET/C# 使用 #if 和 Conditional 特性來按條件編譯代碼的不同原理和適用場景
條件編譯符號和預(yù)處理符號
我們有時會使用 #if DEBUG 或者 [Conditional("DEBUG")] 來讓我們的代碼僅在特定的條件下編譯昙楚。
而這里的 DEBUG 是什么呢刽肠?
在我們編寫的 C# 代碼中纯命,這個叫做 “條件編譯符號”(Conditional compilation symbols)
在項目的構(gòu)建過程中愿题,這個叫做 “定義常量”(Define constants)
而在將 C# 代碼編譯到 dll 的編譯環(huán)節(jié)损俭,這個叫做 “預(yù)處理符號”(Preprocessor symbols)
本文要討論的是 #if 和 Conditional 的使用,這是在 C# 代碼中的使用場景潘酗,因此杆兵,本文后面都將其稱之為 “條件編譯符號”。
對于C#仔夺,與 C 和 C++ 不同琐脏,您不能對符號賦予數(shù)值;C# 中的 #if 語句是 Boolean,僅測試符號是否已定義日裙。
在項目ConsoleApp1設(shè)置中的生成中定義一個條件編譯符號CONDITIONA吹艇。
下面請看ConsoleApp1的示例
using System;
namespace ConsoleApp1
{
public class Class1
{
[Conditional("CONDITIONA")]
public static void Hello1()
{
Console.WriteLine("Hello,我是Conditional條件下才可以執(zhí)行的函數(shù)1");
}
public static void Hello2()
{
#if CONDITIONA
Console.WriteLine("Hello,我是#if條件下才可以執(zhí)行的函數(shù)語句2");
#endif
}
}
class Hello
{
static void Main(string[] args)
{
Class1.Hello1();
Class1.Hello2();
Console.ReadKey();
}
}
}
執(zhí)行結(jié)果
由此,我們得到了#if與Conditional的第一個區(qū)別:
在這段代碼中昂拂,#if CONDITIONA和 #endif 之間的代碼僅在設(shè)置CONDITIONA后會編譯受神,不配置是不會編譯的。
Conditional影響的格侯,是調(diào)用這個方法的代碼鼻听。調(diào)用這個方法的代碼,僅在 CONDITIONA下會編譯联四,在其他配置下是不會編譯的撑碴。
這也引出了#if與Conditional的第二個區(qū)別:
因為 #if CONDITIONA和 #endif 僅僅影響包含在其內(nèi)的代碼塊,因此其僅僅影響寫的這點代碼所在的項目(或者說程序集)碎连。于是使用 #if 只會影響實現(xiàn)代碼灰羽。
而 [Conditional("CONDITIONA")] 影響的是調(diào)用它的代碼,因此可以設(shè)計作為 API 使用——讓目標(biāo)項目(或者程序集)僅在目標(biāo)項目特定的配置下才會編譯鱼辙。
上面是博主呂毅的官方解釋廉嚼,我這里舉個例子吧。
我們新建一個ConsoleApp2,倒戏,添加引用ConsoleApp1.
寫一個新類
using System;
using ConsoleApp1;
namespace ConsoleApp2
{
class Program
{
static void Main(string[] args)
{
Class1.Hello1();//Class1是ConsoleApp1中的類
Class1.Hello2();
Console.ReadKey();
}
}
}
關(guān)鍵就在于設(shè)置這個條件編譯變量上
當(dāng)你為ConsoleApp1項目設(shè)置了CONDITIONA怠噪,Hello2()打印字符串。
當(dāng)你為ConsoleApp2項目設(shè)置了CONDITIONA杜跷,執(zhí)行Hello1()傍念,打印字符串。
實驗:
為ConsoleApp1項目設(shè)置CONDITIONA葛闷,不為ConsoleApp2項目設(shè)置CONDITIONA憋槐。
Hello,我是#if條件下才可以執(zhí)行的函數(shù)語句2
不為ConsoleApp1項目設(shè)置CONDITIONA,為ConsoleApp2項目設(shè)置CONDITIONA淑趾。
Hello,我是Conditional條件下才可以執(zhí)行的函數(shù)1
為ConsoleApp1項目設(shè)置CONDITIONA阳仔,為ConsoleApp2項目設(shè)置CONDITIONA。
Hello,我是Conditional條件下才可以執(zhí)行的函數(shù)1
Hello,我是#if條件下才可以執(zhí)行的函數(shù)語句2
以此為例扣泊,就可以深刻體會以下的結(jié)論了:
因為 #if CONDITIONA和 #endif 僅僅影響包含在其內(nèi)的代碼塊近范,因此其僅僅影響寫的這點代碼所在的項目(或者說程序集)。于是使用 #if 只會影響實現(xiàn)代碼延蟹。
而 [Conditional("CONDITIONA")] 影響的是調(diào)用它的代碼评矩,因此可以設(shè)計作為 API 使用——讓目標(biāo)項目(或者程序集)僅在目標(biāo)項目特定的配置下才會編譯。
用Conditional屬性的方式阱飘,方法是否生效是取決于調(diào)用方斥杜,而用#if方式虱颗,方法是否生效是取決于方法定義所在的程序集。