C # if / then chỉ thị cho gỡ lỗi và phát hành


432

Trong thuộc tính Giải pháp, tôi có Cấu hình được đặt thành "phát hành" cho dự án một và duy nhất của mình.

Khi bắt đầu thói quen chính, tôi có mã này và nó đang hiển thị "Chế độ = Gỡ lỗi". Tôi cũng có hai dòng này ở trên cùng:

#define DEBUG 
#define RELEASE

Tôi đang kiểm tra biến đúng?

#if (DEBUG)
            Console.WriteLine("Mode=Debug"); 
#elif (RELEASE)
            Console.WriteLine("Mode=Release"); 
#endif

Mục tiêu của tôi là đặt các giá trị mặc định khác nhau cho các biến dựa trên chế độ gỡ lỗi và chế độ phát hành.


13
Bạn đang xác định BÓNG gỡ lỗi và phát hành.
Eric Dahlvang

Câu trả lời:


718

DEBUG/ _DEBUGnên được định nghĩa trong VS rồi.

Loại bỏ #define DEBUGtrong mã của bạn. Đặt bộ tiền xử lý trong cấu hình bản dựng cho bản dựng cụ thể đó.

Lý do nó in "Chế độ = Gỡ lỗi" là do bạn #definevà sau đó bỏ qua elif.

Cách đúng để kiểm tra là:

#if DEBUG
    Console.WriteLine("Mode=Debug"); 
#else
    Console.WriteLine("Mode=Release"); 
#endif

Đừng kiểm tra RELEASE.


77
Tôi muốn thêm rằng nếu một người chỉ muốn kiểm tra

3
Tại sao #ifvà không #ifdef?
Bob Stein

23
@ BobStein-VisiBone Hãy nhớ rằng chúng ta đang nói về C # ở đây, không phải C. #ifdeflà dành riêng cho bộ tiền xử lý của C / C ++, C # bắt buộc sử dụng #if.
jduncanator

27
@Jess, tôi tin rằng đây là Visual Studio đang làm
mờ

1
@DakotahHicock Đúng vậy, tôi không sử dụng tính năng chia sẻ lại và VS làm mờ nó đi.
makoshichi

294

Theo mặc định, Visual Studio định nghĩa DEBUG nếu dự án được biên dịch ở chế độ Gỡ lỗi và không xác định nó nếu nó ở chế độ Phát hành. Theo mặc định, RELEASE không được xác định trong chế độ Phát hành. Sử dụng một cái gì đó như thế này:

#if DEBUG
  // debug stuff goes here
#else
  // release stuff goes here
#endif

Nếu bạn muốn làm một cái gì đó chỉ trong chế độ phát hành:

#if !DEBUG
  // release...
#endif

Ngoài ra, đáng để chỉ ra rằng bạn có thể sử dụng [Conditional("DEBUG")]thuộc tính trên các phương thức quay lại voidđể chúng chỉ được thực thi nếu một biểu tượng nhất định được xác định. Trình biên dịch sẽ loại bỏ tất cả các cuộc gọi đến các phương thức đó nếu biểu tượng không được xác định:

[Conditional("DEBUG")]
void PrintLog() {
    Console.WriteLine("Debug info");
}

void Test() {
    PrintLog();
}

6
Câu trả lời tuyệt vời, đánh giá cao.
Duy Trần

210

Tôi thích kiểm tra nó như thế này hơn là tìm kiếm các #definechỉ thị:

if (System.Diagnostics.Debugger.IsAttached)
{
   //...
}
else
{
   //...
}

Với sự cảnh báo tất nhiên là bạn có thể biên dịch và triển khai một cái gì đó trong chế độ gỡ lỗi nhưng vẫn không có trình gỡ lỗi kèm theo.


1
Cảm ơn bạn! Tôi thậm chí còn không biết "#defines" là gì vì vậy đây là một giải pháp tuyệt vời!
Tim

Và tôi là trường hợp của tôi, đây là chính xác những gì tôi muốn. Tôi thực sự muốn biết nếu tôi có trình gỡ lỗi được đính kèm, bởi vì tôi biết tôi có một số mã tôi không muốn thực thi nếu tôi có trình gỡ lỗi được đính kèm. Điều này thật tuyệt!
JFTxJ

1
Nếu cá nhân thích sử dụng #IF DEBUGtrong tình huống mã gỡ lỗi không nên kéo dài. Đối với mã sản xuất tôi đồng ý với việc sử dụng ở trên.
Coops

10
Hạn chế của việc làm này thay vì sử dụng #DEBUGlà câu lệnh if này nằm trong mã của bạn và luôn được kiểm tra khi #DEBUGcâu trả lời loại bỏ mã không áp dụng được tại thời điểm biên dịch để bạn không kiểm tra thời gian chạy và của bạn. exe (hoặc bất cứ điều gì bạn biên dịch thành) nhỏ hơn.
Dan

1
@ người dùng34660. Câu trả lời cho câu hỏi đã nêu là "không", điều này không thực sự giúp được ai.
Steve Smith

51

Tôi không phải là một fan hâm mộ lớn của các công cụ #if, đặc biệt là nếu bạn phát tán nó xung quanh cơ sở mã của mình vì nó sẽ gây ra cho bạn các vấn đề khi bản dựng Debug vượt qua nhưng bản dựng phát hành thất bại nếu bạn không cẩn thận.

Vì vậy, đây là những gì tôi đã đưa ra (lấy cảm hứng từ #ifdef trong C # ):

public interface IDebuggingService
{
    bool RunningInDebugMode();
}

public class DebuggingService : IDebuggingService
{
    private bool debugging;

    public bool RunningInDebugMode()
    {
        //#if DEBUG
        //return true;
        //#else
        //return false;
        //#endif
        WellAreWe();
        return debugging;
    }

    [Conditional("DEBUG")]
    private void WellAreWe()
    {
        debugging = true;
    }
}

2
Này, thật là sáng tạo. Tôi thích việc bạn sử dụng thuộc tính để đặt thuộc tính.
kenchilada

3
Điều này có lợi thế là không bị ảnh hưởng bởi việc tái cấu trúc các lỗi trong Resharper có thể gây rối mã của bạn dựa trên thiết lập có điều kiện hiện tại.
Jafin

3
Tôi thích điều này nhưng tôi tự hỏi tại sao không tạo ra một triển khai đơn lẻ cho việc này thay vì một dịch vụ. Đó là hệ thống cụ thể và nó ngăn bạn phải lo lắng về việc tiêm nó ở mọi nơi. (bạn có thể dự tính một kịch bản trong đó việc thực hiện chức năng này sẽ khác đi không?
BastanteCaro

1
Tôi thực sự có một triển khai dịch vụ và đơn lẻ trong một lớp mà tôi hiện đang sử dụng để bạn có quyền lựa chọn sử dụng nó ... Tất nhiên việc triển khai dịch vụ có lợi ích là dễ dàng "khai thác" hơn rằng bạn có thể kiểm tra cả hai đường dẫn mã ...
Tod Thomson

Tôi tự hỏi tại sao DebuggingServicekhông phải là một lớp tĩnh và tại sao bạn cần một giao diện? Đây có phải là một cái gì đó để làm với việc sử dụng này với một container IoC?
Ben

23
bool isDebug = false;
Debug.Assert(isDebug = true); // '=', not '=='

Phương thức Debug.Assertcó thuộc tính có điều kiện DEBUG. Nếu nó không được xác định, cuộc gọi và chuyển nhượng isDebug = true sẽ bị loại bỏ :

Nếu biểu tượng được xác định, cuộc gọi được bao gồm; mặt khác, cuộc gọi (bao gồm cả việc đánh giá các tham số của cuộc gọi) bị bỏ qua.

Nếu DEBUGđược định nghĩa, isDebugđược đặt thành true(và được chuyển sang Debug.Assert, không có gì trong trường hợp đó).


Đây cũng là một giải pháp khá sáng tạo. :)
Jack

Đẹp. Đối với một biến lặp cần phải thay đổi giữa Gỡ lỗi và Phát hành ... var iterations = 10; Debug.Assert((iterations = Int32.MaxValue) > 0);
Matt Davis

19

Nếu bạn đang cố gắng sử dụng biến được xác định cho loại bản dựng, bạn nên xóa hai dòng ...

#define DEBUG  
#define RELEASE 

... những thứ này sẽ gây ra #if (DEBUG) luôn luôn đúng.

Cũng không có một mặc định điều kiện biên soạn biểu tượng cho CHÍ . Nếu bạn muốn xác định một đi đến các thuộc tính của dự án, bấm vào tab Build và sau đó thêm ĐÁNG TIN CẬY vào hộp văn bản biểu tượng biên dịch có điều kiện trong phần Chung tiêu đề .

Tùy chọn khác là làm điều này ...

#if DEBUG
    Console.WriteLine("Debug");
#else
    Console.WriteLine("Release");
#endif

7

Xóa định nghĩa của bạn ở trên cùng

#if DEBUG
        Console.WriteLine("Mode=Debug"); 
#else
        Console.WriteLine("Mode=Release"); 
#endif

7

Phiên bản câu trả lời được sửa đổi một chút (bastardized?) Của Tod Thomson là một hàm tĩnh chứ không phải là một lớp riêng biệt (tôi muốn có thể gọi nó trong chế độ xem WebForm từ lớp viewutils mà tôi đã đưa vào).

public static bool isDebugging() {
    bool debugging = false;

    WellAreWe(ref debugging);

    return debugging;
}

[Conditional("DEBUG")]
private static void WellAreWe(ref bool debugging)
{
    debugging = true;
}

6

Hãy chắc chắn xác định hằng số DEBUG trong Thuộc tính xây dựng dự án. Điều này sẽ cho phép #if DEBUG. Tôi không thấy hằng số ĐÁNG TIN CẬY được xác định trước, do đó có thể ngụ ý rằng bất cứ điều gì Không nằm trong khối DEBUG đều là chế độ ĐÁNG TIN CẬY.

Xác định hằng số DEBUG trong Thuộc tính xây dựng dự án


5

Tên không gian

using System.Resources;
using System.Diagnostics;

phương pháp

   private static bool IsDebug()
    {
        object[] customAttributes = Assembly.GetExecutingAssembly().GetCustomAttributes(typeof(DebuggableAttribute), false);
        if ((customAttributes != null) && (customAttributes.Length == 1))
        {
            DebuggableAttribute attribute = customAttributes[0] as DebuggableAttribute;
            return (attribute.IsJITOptimizerDisabled && attribute.IsJITTrackingEnabled);
        }
        return false;
    }

3

Một mẹo có thể giúp bạn tiết kiệm rất nhiều thời gian - đừng quên điều đó ngay cả khi bạn chọn debug theo cấu hình bản dựng (trên menu vs2012 / 13, nó nằm trong BUILD => QUẢN LÝ CẤU HÌNH) - điều đó là không đủ.

Bạn cần chú ý đến CÔNG KHAI Configuration, như sau:

nhập mô tả hình ảnh ở đây


0

Vì mục đích của các chỉ thị MÁY TÍNH này là yêu cầu trình biên dịch KHÔNG bao gồm mã, mã gỡ lỗi, mã beta hoặc có lẽ là mã cần thiết cho tất cả người dùng cuối của bạn, ngoại trừ những bộ phận quảng cáo, ví dụ như #Define AdDept bạn muốn có thể bao gồm hoặc loại bỏ chúng dựa trên nhu cầu của bạn. Không phải thay đổi mã nguồn của bạn nếu ví dụ không phải AdDept hợp nhất vào AdDept. Sau đó, tất cả những gì cần làm là đưa chỉ thị #AdDept vào trang thuộc tính tùy chọn trình biên dịch của phiên bản hiện có của chương trình và thực hiện biên dịch và wa la! mã nguồn của chương trình hợp nhất còn sống!.

Bạn cũng có thể muốn sử dụng một khai báo cho một quy trình mới chưa sẵn sàng cho thời gian chính hoặc không thể hoạt động trong mã cho đến khi đến lúc phát hành nó.

Nhưng dù sao, đó là cách tôi làm.


0

Tôi đã suy nghĩ về một cách tốt hơn. Tôi nhận ra rằng các khối #if là nhận xét hiệu quả trong các cấu hình khác (giả sử DEBUGhoặc RELEASE; nhưng đúng với bất kỳ biểu tượng nào)

public class Mytest
    {
        public DateTime DateAndTimeOfTransaction;
    }

    public void ProcessCommand(Mytest Command)
        {
            CheckMyCommandPreconditions(Command);
            // do more stuff with Command...
        }

        [Conditional("DEBUG")]
        private static void CheckMyCommandPreconditions(Mytest Command)
        {
            if (Command.DateAndTimeOfTransaction > DateTime.Now)
                throw new InvalidOperationException("DateTime expected to be in the past");
        }

0

Xóa các định nghĩa và kiểm tra xem điều kiện có ở chế độ gỡ lỗi không. Bạn không cần kiểm tra xem lệnh có ở chế độ phát hành hay không.

Một cái gì đó như thế này:

#if DEBUG
     Console.WriteLine("Mode=Debug"); 
#else
    Console.WriteLine("Mode=Release"); 
#endif
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.