2010-10-01 116 views
23

在C/C++,你可以在代碼中定義的宏是這樣的:如何設置條件編譯變量?

#define OLD_WAY 1 

雖然我從來沒有做過,我認爲同樣的事情在C#中可用。更重要的是,在C/C++,可以再由做這樣的事情做一些條件編譯邏輯:

#if OLD_WAY == 1 
int i = 0; 
#else 
int i = 1; 
#endif 

OK,所以這是所有的涼爽和所有。再次,我假設這種邏輯在C#中是可能的。我想知道的是,如何在項目級別定義常量,以便我可以放入邏輯,以便我可以有條件地編譯一段代碼,如果我定義一個常量或另一個代碼塊如果我不這樣定義它?我假設它是在項目的屬性中完成的,但我如何以及在哪裏定義它?

回答

19

C#編譯器csc.exe和C#語言本身不會爲conditional compilation公開任何預定義的常量。 VisualStudio僅添加了可通過IDE配置的DEBUGTRACE值。 IDE還允許您添加自己的任意符號,但由於這些符號基本上是固定的(不變的)值,因此該功能的使用受到限制。

更強大的自定義選項可以通過手動編輯您的.csproj項目文件來設置。根據MSBuild(見herehere)提供的大量環境和配置信息,您可以在這裏將conditions設置爲selectively propagateselectively propagate條件編譯爲C#,但原則上可能沒有完整列表,因爲不同組件會任意貢獻元數據特設)。

讓我們考慮一個工作示例。有條件編譯有用的一種情況是,如果您想編寫適合構建過程中發現的任何工具的代碼。通過這種方式,您可以利用最新的語言功能,同時仍能夠保留在具有較舊工具的機器上進行編譯的能力,而這正如預期的那樣會拒絕外來語法和/或關鍵字。對於C# 7.0vs2017特定的情況下,我們可以通過修改.csproj如下:

.csproj的文件(節選):

enter image description here

您還可以識別每個上了年紀的C#編譯器,以及,一路上優雅地退化。這同樣適用於檢測所述.NET Framework版本(經常要求在計算器上[1] [2] [3] [4])和任何其它環境條件的構建。這些作爲練習留給讀者,但如果你想從上面複製/粘貼突出顯示的行,這裏是文本版本。由於在截屏的更新,我加了單引號的條件表達式這裏(即使一切似乎沒有他們的工作)

<DefineConstants Condition="'$(VisualStudioVersion)'=='15'">CSHARP7</DefineConstants> 
<!-- ... --> 
<DefineConstants>DEBUG;TRACE;$(DefineConstants)</DefineConstants> 
<!-- ... --> 
<DefineConstants>TRACE;$(DefineConstants)</DefineConstants> 

不管怎麼說,以這種方式,你現在就可以編寫使用#if… #elif… #else… #endif有條件的C#代碼 。繼續這個例子,下面的代碼使用新的元組語法 - 只在C#7中可用 - 交換數組元素。順便提一句,元組版本不僅更簡潔和/或優雅,它也產生優異的IL代碼:

#if CSHARP7 
    (rg[i], rg[j]) = (rg[j], rg[i]); // swap elements: tuple syntax 
#else 
    var t = rg[i];     // swap elements: clunky 
    rg[i] = rg[j]; 
    rg[j] = t; 
#endif 

注意,Visual Studio IDE 確實正確處理您的人工.csproj自定義在每一個方面。鑑於.csproj我之前展示的IDE代碼編輯器可以正確識別和評估爲目的,條件編譯IntelliSenserefactoring,「調出」的代碼不激活塊等

我也提到了MSBuild有一個寶庫的信息可用,其中$(VisualStudioVersion)只是一個例子。不幸的是,不容易找出哪些值是可用的,以及它們在構建時可能具有的值。一個訣竅就是臨時把C++項目放到你的C#項目旁邊的Visual Studio解決方案中(如果你還沒有的話)。如果您右鍵點擊項目屬性對於此.vcxproj,然後查看(例如,)「附加包含目錄」的C/C++頁面上,一個下拉菜單會出現在最右邊,當您單擊編輯:

enter image description here

你會得到一個對話框,以「宏」按鈕,就可以單擊以獲取所有可用變量的列表以及根據當前在IDE中選擇的平臺和配置的預期值。請不要忽略列表底部的well-known-item-metadata字段(前綴爲%)。

enter image description here

你可以得到很多東西是如何在這裏從這張截圖的滾動條拇指大小的想法。 (它們按字母順序排列,我只是滾動到「P」部分的這部分,因爲它的個人信息很少)。然而,需要注意的是,在構建過程中,(可用)變量及其值隨着時間的推移而變化,因此您可能會發現此列表中的項目在處理時不可用於您的.csproj

+0

Awsome!這個答案需要更多的投票!特別是對於C++提示:-) – Matt 2017-05-12 13:16:16

27

打開您的項目屬性並查看Build頁面。有一個名爲Conditional compilation symbols的框。

enter image description here

+1

@toddmo你在說什麼?它在VS2015中的位置與15年前的每個版本都一樣。 – 2016-11-05 16:25:51

31

在C#中,你可以做#define但就像你可以在C++中,不能對他們使用的值。
每個定義可以有2個狀態:已定義或未定義

在Build下的項目屬性中,您可以設置應該定義的定義。
您在此處指定的任何內容都將在所有項目文件中定義。

因此,例如,我可以在此字段定義2個條件編譯符號爲:
MY_DEFINE1, MY_DEFINE2

這樣便在我的代碼,我可以做的事情:

#if MY_DEFINE1 
//do something conditionally 
#endif 

#if MY_DEFINE2 
//do something else conditionally 
#endif 

或者你可以做你的定義每個文件,但與C++不同,它們必須位於文件的頂部。

在你的文件的頂部,你可以使用:

#define MY_DEFINE2 

,或者你可以在你的文件使用的頂部:

#undef MY_DEFINE2 

如果設置了這最後一個,你會怎麼做有條件的編譯符號,並且您希望除了一個文件以外的所有文件。

相關問題