โค้ด "แก้จุดบกพร่องเท่านั้น" ที่ควรทำงานเมื่อ "เปิด" เท่านั้น


94

ฉันต้องการเพิ่มโค้ด C # "debug only" บางส่วนที่ทำงานเฉพาะในกรณีที่ผู้ทำการดีบักร้องขอ ใน C ++ ฉันเคยทำสิ่งที่คล้ายกับสิ่งต่อไปนี้:

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
 // ...
}

ฉันไม่สามารถทำสิ่งเดียวกันใน C # ได้ทุกประการเนื่องจากไม่มีสถิติท้องถิ่น

คำถาม : อะไรคือวิธีที่ดีที่สุดในการทำสิ่งนี้ให้สำเร็จใน C #?

  1. ฉันควรใช้ private class static field กับ C # preprocessor directives ( #if/#endif DEBUG) หรือไม่?
  2. ฉันควรใช้แอ็ตทริบิวต์ Conditional (เพื่อเก็บโค้ด) จากนั้นเลือกฟิลด์สแตติกคลาสส่วนตัว ( ไม่ได้ล้อมรอบด้วยคำสั่ง C # พรีโปรเซสเซอร์#if/#endif DEBUGหรือไม่)
  3. อื่น ๆ อีก?

คำตอบ:


149

ตัวแปรอินสแตนซ์น่าจะเป็นวิธีทำสิ่งที่คุณต้องการ คุณสามารถกำหนดให้คงที่เพื่อคงค่าเดิมตลอดอายุการใช้งานของโปรแกรม (หรือเธรดขึ้นอยู่กับโมเดลหน่วยความจำแบบคงที่ของคุณ) หรือทำให้เป็นอินสแตนซ์ทั่วไปเพื่อควบคุมตลอดอายุของอินสแตนซ์อ็อบเจ็กต์ หากอินสแตนซ์นั้นเป็นซิงเกิลตันพวกมันจะทำงานในลักษณะเดียวกัน

#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
 // ...
}

เพื่อให้สมบูรณ์ pragmas (คำสั่งก่อนตัวประมวลผล) ถือเป็นส่วนหนึ่งของ kludge ที่ใช้ควบคุมการไหลของโปรแกรม .NET มีคำตอบในตัวสำหรับปัญหานี้ครึ่งหนึ่งโดยใช้แอตทริบิวต์ "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.
  }    
  // ...
}

ไม่มี pragmas สะอาดกว่ามาก ข้อเสียคือ Conditional สามารถใช้ได้กับเมธอดเท่านั้นดังนั้นคุณจะต้องจัดการกับตัวแปรบูลีนที่ไม่ได้ทำอะไรเลยในรีลีสบิลด์ เนื่องจากตัวแปรมีอยู่เพียงเพื่อสลับจากโฮสต์การดำเนินการ VS และในรีลีสสร้างค่าของมันไม่สำคัญจึงไม่เป็นอันตราย


2
สุดท้าย - คนที่อ่านคำถามทั้งหมด ขอบคุณโอเค - ดูเหมือนว่าจะเป็นวิธีการแก้ปัญหาที่ยาว (ต้องมีส่วนเตรียมการประมวลผลสองส่วน) แต่อาจเป็น C # ที่ดีที่สุดที่สามารถทำได้ในสิ่งที่ฉันต้องการ
Matt Smith

7
ฉัน. ฉันจะไม่เรียกสิ่งนี้ว่ายาวเพียงเพราะคุณเพิ่มคำสั่งพรีโปรเซสเซอร์อีกสองบรรทัด
KeithS

4
ขอขอบคุณแพทริคมากสำหรับการลงคะแนนคำตอบที่ได้รับการยอมรับ 3 ปีซึ่งไม่สามารถแก้ปัญหาทั้งหมดได้ แอตทริบิวต์ที่มีเงื่อนไขจะป้องกันเฉพาะเมธอดที่ดำเนินการในโหมดที่ไม่ใช่การดีบัก OP ไม่ต้องการเพียงแค่นั้น แต่ยังสามารถ "เปิด" โค้ดโดยใช้ดีบักเกอร์ และแท็กของ gokkor ตามที่ใช้จะไม่คอมไพล์
KeithS

2
โปรดทราบว่าตัวประมวลผลล่วงหน้าจะบอกคุณว่าโปรแกรมกำลังคอมไพล์อยู่ในโหมดดีบัก แต่ไม่เชื่อมต่อระหว่างที่ดีบักเกอร์กำลังทำงานอยู่
เชน

66

สิ่งที่คุณกำลังมองหาคือ

[ConditionalAttribute("DEBUG")]

แอตทริบิวต์

ตัวอย่างเช่นหากคุณเขียนวิธีการเช่น:

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

การเรียกใช้วิธีนี้ภายในรหัสของคุณเองจะดำเนินการในโหมดดีบักเท่านั้น หากคุณสร้างโปรเจ็กต์ของคุณในโหมดรีลีสแม้แต่การเรียกใช้ "MyLovelyDebugInfoMethod" ก็จะถูกละเว้นและถูกทิ้งออกจากไบนารีของคุณ

อ้อและอีกประการหนึ่งหากคุณกำลังพยายามตรวจสอบว่าโค้ดของคุณกำลังถูกดีบักในขณะดำเนินการหรือไม่คุณยังสามารถตรวจสอบได้ว่ากระบวนการปัจจุบันถูกเชื่อมโยงโดย JIT หรือไม่ แต่นี่เป็นอีกกรณีหนึ่ง แสดงความคิดเห็นหากนี่คือสิ่งที่คุณกำลังพยายามทำอยู่


5
เมื่อใช้ Attribute คุณไม่จำเป็นต้องเขียนคำต่อท้าย "Attribute" Conditional = ConditionalAttribute คลาสแอตทริบิวต์ควรลงท้ายด้วย "แอตทริบิวต์" แต่สามารถละเว้นได้เมื่อใช้เป็นแอตทริบิวต์ในโค้ด อ่านได้ง่ายขึ้นเมื่อละเว้นคำต่อท้าย
Eric Ouellet

23

คุณสามารถลองใช้สิ่งนี้ได้หากคุณต้องการให้โค้ดทำงานเมื่อคุณมีดีบักเกอร์ที่แนบมากับกระบวนการเท่านั้น

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

ขอขอบคุณ! นี่คือสิ่งที่ฉันต้องการ: ทำ Console.ReadLine () ในตอนท้ายเพื่อป้องกันการปิดหน้าต่างคอนโซลเมื่อทำการดีบัก
VVS

4

ฉันคิดว่ามันอาจจะคุ้มค่าที่จะกล่าวถึงที่[ConditionalAttribute]อยู่ในSystem.Diagnostics;เนมสเปซ ฉันสะดุดเล็กน้อยเมื่อได้:

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

หลังจากใช้ครั้งแรก (คิดว่าน่าจะเข้าแล้วSystem)


3

หากคุณต้องการทราบว่ามีการดีบักทุกที่ในโปรแกรมหรือไม่ ใช้สิ่งนี้

ประกาศตัวแปรส่วนกลาง

bool isDebug=false;

สร้างฟังก์ชันสำหรับตรวจสอบโหมดดีบัก

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

ในวิธีการเริ่มต้นเรียกใช้ฟังก์ชัน

isDebugging();

ตอนนี้อยู่ในโปรแกรมทั้งหมด คุณสามารถตรวจสอบการดีบักและดำเนินการได้ หวังว่านี่จะช่วยได้!


1
AFAIK: สิ่งนี้และตัวแปรในที่นี้เป็นเพียงวิธีเดียวที่จะทราบได้ว่าโปรแกรมล้างที่คอมไพล์ด้วยชุดค่าสถานะดีบักหรือไม่
LosManos
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.