2011-11-22 40 views
54

C# có khôngConditional (!Conditional, NotConditional, Conditional(!)) thuộc tính?C#! Thuộc tính có điều kiện?


tôi biết C# có một Conditional attribute:

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

tương đương tới:

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

Nhưng trong trường hợp này tôi muốn ngược hành vi (bạn có cụ thể là chọn không tham gia):

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

Dẫn tôi thử:

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

mà không biên dịch. Và:

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

không biên dịch. Và:

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

không biên dịch vì đó chỉ là suy nghĩ mơ ước.

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

+5

Nope. Lưu ý rằng '[Conditional (...)]' không tương đương với điều đó; nó cũng loại bỏ các cuộc gọi. – SLaks

+0

@SLaks: Tôi đã viết một câu trả lời bao gồm cả điểm đó :) –

Trả lời

45

Thứ nhất, có thuộc tính Conditionalkhông tương đương với việc có #if thay vì phương pháp này. Xem xét:

ShowDebugString(MethodThatTakesAges()); 

Với hành vi thực sự của ConditionalAttribute, MethodThatTakesAges không được gọi là - toàn bộ cuộc gọi bao gồm lập luận đánh giá được lấy ra từ các trình biên dịch.

Tất nhiên điểm khác là nó phụ thuộc vào những biểu tượng tiền xử lý thời gian biên dịch tại thời gian biên dịch của gọi, không phải của các phương pháp :)

Nhưng không, tôi không tin có bất cứ điều gì làm những gì bạn muốn ở đây. Tôi vừa kiểm tra phần C# spec 17.4.2 mà nó đề cập đến các phương thức có điều kiện và các lớp thuộc tính có điều kiện, và không có gì trong đó cho thấy có bất kỳ cơ chế nào như vậy.

+0

Gần nhất bạn có thể nhận được một cách sạch sẽ là giải pháp của SLAKS bên dưới. – NoxMortem

0

Thư viện chuẩn tiêu chuẩn khuôn khổ NET Thư viện chuẩn được chú thích không nêu rõ bất kỳ điều gì. Vì vậy, tôi sợ bạn sẽ phải cuộn của riêng bạn!

+0

Điều đó là không thể. – SLaks

4
#ifndef ShowDebugString 
#define RemoveSDS 
#endif 

?

chỉnh sửa: Để biết rõ hơn. Nếu ShowDebugString được định nghĩa Conditional["ShowDebugString"] sẽ được gọi. Nếu ShowDebugString không được xác định, Conditional["RemoveSDS"] sẽ được gọi.

+1

Điều này sẽ cần phải được trong * gọi * mã mặc dù - trong mỗi tập tin mà các tính năng được yêu cầu. Nó khác với những gì được yêu cầu, IMO. –

+0

@JonSkeet +1 để đề cập đến giá trị của bản sửa lỗi toàn cục, thay vì yêu cầu tất cả mọi người thay đổi tất cả mã hiện có (http://stackoverflow.com/questions/244246/c-alias-a-class-name) –

+0

Giải pháp tốt nhất là có khả năng thêm một định nghĩa mới ở cấp dự án có giá trị chính xác/dự kiến ​​cho mỗi cấu hình xây dựng. – James

34

Không.

Thay vào đó, bạn có thể viết

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

Lưu ý rằng không giống như [Conditional], điều này sẽ được quyết định bởi sự hiện diện của các biểu tượng trong lắp ráp của bạn, chứ không phải trong lắp ráp của người gọi của bạn.

+0

Đây thực sự là giải pháp tốt nhất, tuy nhiên tôi khuyên bạn nên sử dụng một băm ngẫu nhiên dài thay vì FALSE, có thể được đặt trong một số assembly. – NoxMortem

8

Chỉ cần thêm 2 xu, ba năm xuống dòng :-) ... Tôi sử dụng phương thức [Conditional("DEBUG")] để đặt thuộc tính IsDebugMode để kiểm tra đảo ngược. Hacky, nhưng nó hoạt động:

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

Tại sao bạn lại làm điều này? Tại sao không chỉ sử dụng một cái gì đó như '#if DEBUG trả về true; #else return false; # endif'? –

+2

Hãy xem cuộc thảo luận chuyên sâu này về giá trị của việc sử dụng các thẻ pragma và các thuộc tính có điều kiện. Đó là quá nhiều để giải thích trong một bình luận: http://stackoverflow.com/questions/3788605/if-debug-vs-conditionaldebug – Heliac

+0

Tôi sẽ viết một cái gì đó như thế này, tôi vui vì bạn đã làm nó cho tôi, nhưng nó kỳ lạ rằng câu trả lời này là như vậy dưới đây. Tôi không nghĩ rằng nó hoạt động nếu mã này là trong một hội đồng khác nhau mặc dù, bởi vì quyết định nếu "CheckDebugMode" được gọi là hay không được thực hiện khi bạn lắp ráp nó, không phải khi bạn gọi nó. Theo nghĩa này, nó khá giống với việc sử dụng dấu #if để kiểm tra. –

14

Đúng là chúng ta không thể 'KHÔNG' có điều kiện Thuộc tính, nhưng chúng ta có thể 'KHÔNG' điều kiện như được trình bày bên dưới.

// 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"); 
} 

hy vọng điều này giúp bạn giải quyết vấn đề của bạn;)

+2

-1 Rất tốt, nhưng điều này không phải lúc nào cũng hoạt động vì điều này không phụ thuộc vào các biểu tượng tiền xử lý biên dịch của người gọi (đặc biệt nếu người gọi ở trên một assembly khác, hoặc một module khác trong cùng một assembly). – Kryptos

+0

Có nó phụ thuộc vào ngữ cảnh trình biên dịch của người gọi cho tất cả các assembly tại thời gian biên dịch (điều kiện #if phải ở trong ngữ cảnh người gọi như C# standard nói). Không bao giờ nói nó sẽ làm việc hay không nếu chúng ta đặt điều kiện #if trong một hội đồng khác, và đó không phải là câu hỏi của OP. Vì vậy, nếu tôi có thể hỏi tại sao bỏ phiếu xuống? – SoLaR

Các vấn đề liên quan