2011-11-22 78 views
54

請問C#有而不是Conditional!Conditional,NotConditional, Conditional(!))屬性?C#!條件屬性?


我知道C#有一個Conditional attribute

[Conditional("ShowDebugString")] 
public static void ShowDebugString(string s) 
{ 
    ... 
} 

到這相當於:

public static void ShowDebugString(string s) 
{ 
#if ShowDebugString 
    ... 
#endif 
} 

但在這種情況下,我想行爲(你有特意選擇退出):

public static void ShowDebugString(string s) 
{ 
#if !RemoveSDS 
    ... 
#endif 
} 

這使我嘗試:

[!Conditional("RemoveSDS")] 
public static void ShowDebugString(string s) 
{ 
    ... 
} 

不編譯。並且:

[Conditional("!RemoveSDS")] 
public static void ShowDebugString(string s) 
{ 
    ... 
} 

不編譯。並且:

[NotConditional("RemoveSDS")] 
public static void ShowDebugString(string s) 
{ 
    ... 
} 

不編譯,因爲它只是一廂情願。

Not true, but true enough. Don't make me bring back the Nitpicker's Corner.

+5

都能跟得上。請注意,'[Conditional(...)]'不等於那個;它也會刪除callites。 – SLaks

+0

@SLaks:我正在寫一個答案,包括這一點:) –

回答

45

首先,具有Conditional屬性是等價於具有#if代替該方法。試想一下:

ShowDebugString(MethodThatTakesAges()); 

隨着ConditionalAttribute真正的行爲,MethodThatTakesAges不會被調用 - 在整個呼叫包括參數評測從編譯器中刪除。

當然的另一點是,它依賴於編譯時預處理符號在呼叫者的編譯時間,不是的方法 :)

但是,沒有,我不相信有什麼是你想要的。我剛剛檢查了C#規範第17.4.2節,它涉及條件方法和條件屬性類,並且沒有任何內容暗示存在任何此類機制。

+0

最接近你可以乾淨地得到的是下面的SLAKS的解決方案。 – NoxMortem

0

NET框架標準庫註釋引用沒有聲明任何。所以我擔心你不得不推出自己的!

+0

這是不可能的。 – SLaks

4
#ifndef ShowDebugString 
#define RemoveSDS 
#endif 

編輯:欲瞭解更多詳情。如果ShowDebugString被定義爲Conditional["ShowDebugString"]將被調用。如果ShowDebugString沒有被定義,Conditional["RemoveSDS"]將被調用。

+1

儘管這需要在*調用代碼中 - 在需要該功能的每個文件中。這與所要求的有很大不同,IMO。 –

+0

@JonSkeet +1提到全局修復的價值,而不是要求每個人都更改所有現有代碼(http://stackoverflow.com/questions/244246/c-alias-a-class-name) –

+0

最佳解決方案是可能會在項目級別添加一個新的定義,該定義具有每個構建配置的正確/期望值。 – James

34

沒有。

相反,你可以寫

#if !ShowDebugString 
[Conditional("FALSE")] 
#endif 

注意,不像[Conditional],這將是由符號的存在在你的裝配決定,而不是在你的來電者的集會。

+0

這實際上是最好的解決方案,但是我強烈建議使用長隨機散列代替FALSE,這可以在某些程序集中設置。 – NoxMortem

8

只需添加我的2美分,三年下來:-) ...我使用[Conditional("DEBUG")]方法設置IsDebugMode屬性來檢查相反。哈克,但它的工作原理如下:

private bool _isDebugMode = false; 
public bool IsDebugMode 
{ 
    get 
    { 
     CheckDebugMode(); 
     return _isDebugMode; 
    } 
} 

[Conditional("DEBUG")] 
private void CheckDebugMode() 
{ 
    _isDebugMode = true; 
} 

private void DisplaySplashScreen() 
{ 
    if (IsDebugMode) return; 

    var splashScreenViewModel = new SplashScreenVM(500) 
    { 
     Header = "MyCompany Deals", 
     Title = "Main Menu Test", 
     LoadingMessage = "Creating Repositories...", 
     VersionString = string.Format("v{0}.{1}.{2}", 
      GlobalInfo.Version_Major, GlobalInfo.Version_Minor, GlobalInfo.Version_Build) 
    }; 

    SplashScreenFactory.CreateSplashScreen(splashScreenViewModel); 
} 
+0

你爲什麼要這樣做?爲什麼不只是使用'#if DEBUG return true; #else返回false; #endif'? –

+2

查看關於使用pragma標籤與條件屬性的優點的深入討論。這是太多解釋在一個評論:http://stackoverflow.com/questions/3788605/if-debug-vs-conditionaldebug – Heliac

+0

我會寫這樣的事情,我很高興你爲我做了這件事,但它是奇怪的是,這個答案如下。 但是,如果此代碼位於不同的程序集中,我認爲它不起作用,因爲決定是否調用「CheckDebugMode」是在組裝它時完成的,而不是在調用它時完成的。 從這個意義上講,它與使用#if來檢查它非常相似。 –

14

真的,我們不能'不'條件屬性,但我們可以'不'條件如下所示。

// at the begining of the code before uses 
#if DUMMY 
#undef NOT_DUMMY 
#else 
#define NOT_DUMMY 
#endif 

// somewhere in class 
[Conditional("NOT_DUMMY")] 
public static void ShowDebugStringNOTDUMMY(string s) 
{ 
    Debug.Print("ShowDebugStringNOTDUMMY"); 
} 


[Conditional("DUMMY")] 
public static void ShowDebugStringDUMMY(string s) 
{ 
    Debug.Print("ShowDebugStringDUMMY"); 
} 

希望這可以幫助你解決你的問題。)

+2

-1不錯的嘗試,但這並不總是奏效,因爲這不依賴於調用者的編譯時預處理器符號(特別是當調用者位於另一個程序集或同一程序集中的另一個模塊時)。 – Kryptos

+0

是的,它取決於編譯時所有程序集調用者的編譯器上下文(條件#if必須在調用者上下文中,如c#標準所述)。從來沒有說過,如果我們把條件#if放在另一個程序集中,它就不會起作用,這不是OP的問題。所以,如果我可能會問爲什麼會投票呢? – SoLaR