Mã “Chỉ gỡ lỗi” chỉ chạy khi được “bật”


93

Tôi muốn thêm một số mã C # "chỉ gỡ lỗi" chỉ chạy nếu người gỡ lỗi yêu cầu nó. Trong C ++, tôi đã từng làm điều gì đó tương tự như sau:

void foo()
{   
  // ...
  #ifdef DEBUG
  static bool s_bDoDebugOnlyCode = false;
  if (s_bDoDebugOnlyCode)
  {
      // Debug only code here gets executed when the person debugging 
      // manually sets the bool above to true.  It then stays for the rest
      // of the session until they set it to false.
  }
  #endif
 // ...
}

Tôi không thể làm chính xác như vậy trong C # vì không có tĩnh cục bộ.

Câu hỏi : Cách tốt nhất để thực hiện điều này trong C # là gì?

  1. Tôi có nên sử dụng trường tĩnh lớp riêng với chỉ thị tiền xử lý C # ( #if/#endif DEBUG) không?
  2. Tôi có nên sử dụng thuộc tính Điều kiện (để giữ mã) và sau đó là trường tĩnh lớp riêng ( không được bao quanh bởi các chỉ thị tiền xử lý C # #if/#endif DEBUGkhông?).
  3. Thứ gì khác?

Câu trả lời:


145

Một biến thể hiện có thể sẽ là cách để thực hiện những gì bạn muốn. Bạn có thể làm cho nó tĩnh để duy trì cùng một giá trị trong thời gian tồn tại của chương trình (hoặc luồng tùy thuộc vào mô hình bộ nhớ tĩnh của bạn) hoặc làm cho nó trở thành một đối tượng var thông thường để kiểm soát nó trong suốt vòng đời của một đối tượng. Nếu trường hợp đó là một singleton, chúng sẽ hoạt động theo cùng một cách.

#if DEBUG
private /*static*/ bool s_bDoDebugOnlyCode = false;
#endif

void foo()
{   
  // ...
#if DEBUG
  if (s_bDoDebugOnlyCode)
  {
      // Code here gets executed only when compiled with the DEBUG constant, 
      // and when the person debugging manually sets the bool above to true.  
      // It then stays for the rest of the session until they set it to false.
  }
#endif
 // ...
}

Nói một cách đầy đủ, pragmas (chỉ thị tiền xử lý) được coi là một phần nhỏ để sử dụng để điều khiển luồng chương trình. .NET có sẵn một câu trả lời cho một nửa vấn đề này, sử dụng thuộc tính "Conditional".

private /*static*/ bool doDebugOnlyCode = false; 
[Conditional("DEBUG")]
void foo()
{   
  // ...    
  if (doDebugOnlyCode)
  {
      // Code here gets executed only when compiled with the DEBUG constant, 
      // and when the person debugging manually sets the bool above to true.  
      // It then stays for the rest of the session until they set it to false.
  }    
  // ...
}

Không có pragmas, sạch hơn nhiều. Nhược điểm là Điều kiện chỉ có thể được áp dụng cho các phương thức, vì vậy bạn sẽ phải đối phó với một biến boolean không có tác dụng gì trong bản dựng phát hành. Vì biến tồn tại duy nhất để được chuyển đổi từ máy chủ thực thi VS và trong một bản phát hành, giá trị của nó không quan trọng, nên nó khá vô hại.


2
Cuối cùng - một người đọc toàn bộ câu hỏi. Cảm ơn, được rồi - nó có vẻ như là một giải pháp dài dòng (phải có hai phần tiền xử lý), nhưng có lẽ đó là điều tốt nhất mà C # có thể làm cho những gì tôi muốn.
Matt Smith

6
meh. Tôi sẽ không gọi điều này dài dòng chỉ vì bạn thêm hai dòng chỉ thị tiền xử lý.
KeithS

4
Cảm ơn Patrick rất nhiều, vì đã từ chối một câu trả lời được chấp nhận của đứa trẻ 3 tuổi thay vì một câu trả lời không giải quyết được toàn bộ vấn đề. Thuộc tính điều kiện chỉ ngăn phương thức thực thi trong chế độ không gỡ lỗi. OP không chỉ muốn vậy mà còn có thể "bật" mã bằng trình gỡ lỗi. Và, thẻ của gokkor khi được sử dụng sẽ không biên dịch.
KeithS

2
Lưu ý rằng bộ xử lý trước cho bạn biết liệu chương trình có đang biên dịch ở chế độ gỡ lỗi hay không, nhưng không làm ướt bộ gỡ lỗi đang thực sự chạy.
Shane

65

Những gì bạn đang tìm kiếm là

[ConditionalAttribute("DEBUG")]

thuộc tính.

Ví dụ, nếu bạn viết một phương thức như:

[ConditionalAttribute("DEBUG")]
public static void MyLovelyDebugInfoMethod(string message)
{
    Console.WriteLine("This message was brought to you by your debugger : ");
    Console.WriteLine(message);
}

bất kỳ lệnh gọi nào bạn thực hiện tới phương thức này bên trong mã của riêng bạn sẽ chỉ được thực hiện ở chế độ gỡ lỗi. Nếu bạn xây dựng dự án của mình ở chế độ phát hành, ngay cả lệnh gọi đến "MyLovelyDebugInfoMethod" sẽ bị bỏ qua và bị loại khỏi tệp nhị phân của bạn.

Ồ và một điều nữa nếu bạn đang cố gắng xác định xem mã của bạn hiện đang được gỡ lỗi tại thời điểm thực thi hay không, thì bạn cũng có thể kiểm tra xem quá trình hiện tại có được nối bởi JIT hay không. Nhưng đây là tất cả cùng một trường hợp khác. Đăng nhận xét nếu đây là điều bạn đang cố gắng thực hiện.


3
Khi sử dụng Thuộc tính, bạn không phải viết hậu tố "Thuộc tính". Có điều kiện = ConditionalAttribute. Một lớp thuộc tính phải kết thúc bằng "Thuộc tính" nhưng có thể bị giới hạn khi được sử dụng làm thuộc tính trong mã. Nó dễ đọc hơn khi hậu tố là không giới hạn.
Eric Ouellet

23

Bạn có thể thử điều này nếu bạn chỉ cần mã chạy khi bạn có trình gỡ lỗi được đính kèm với quy trình.

if (Debugger.IsAttached)
{
     // do some stuff here
}

Cảm ơn bạn! Đây chính xác là những gì tôi muốn: Thực hiện một Console.ReadLine () ở cuối để ngăn việc đóng cửa sổ giao diện điều khiển khi gỡ lỗi.
VVS

4

Tôi nghĩ có thể đáng nói [ConditionalAttribute]là trong System.Diagnostics;không gian tên. Tôi hơi vấp ngã khi nhận được:

Error 2 The type or namespace name 'ConditionalAttribute' could not be found (are you missing a using directive or an assembly reference?)

sau khi sử dụng nó lần đầu tiên (tôi nghĩ rằng nó sẽ được trong System).


3

Nếu bạn muốn biết nếu gỡ lỗi, ở mọi nơi trong chương trình. Dùng cái này.

Khai báo biến toàn cục.

bool isDebug=false;

Tạo chức năng để kiểm tra chế độ gỡ lỗi

[ConditionalAttribute("DEBUG")]
    public static void isDebugging()
    {
        isDebug = true;
    }

Trong phương thức khởi tạo, hãy gọi hàm

isDebugging();

Bây giờ trong toàn bộ chương trình. Bạn có thể kiểm tra gỡ lỗi và thực hiện các hoạt động. Hi vọng điêu nay co ich!


1
AFAIK: điều này và các biến thể ở đây chỉ là cách chắc chắn để biết liệu một chương trình rửa được biên dịch với bộ cờ gỡ lỗi.
LosManos
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.