2010-04-14 45 views
4

我已經寫了調試一個簡單的類,我叫我的代碼的方法Debugger.WriteLine(...)這樣的:有關的問題在C#中的有效記錄

Debugger.WriteLine("[Draw]", "InProgress", 
    "[x,y] = " + x.ToString("0.00") + 
    ", " + y.ToString("0.00") + 
    "; pos = " + lastPosX.ToString() + "x" + 
    lastPosY.ToString() + " -> " + posX.ToString() + 
    "x" + posY.ToString() + "; SS = " + 
    squareSize.ToString() + "; MST = " + 
    startTime.ToString("0.000") + "; Time = " + time.ToString() + 
    phase.ToString(".0000") + "; progress = " + 
    progress.ToString("0.000") + "; step = " + 
    step.ToString() + "; TimeMovementEnd = " + 
    UI.MovementEndTime.ToString() 
); 

程序調試器的主體.WriteLine僅在調試模式下編譯(指令#if,#endif)。讓我擔心的是我經常需要在Debugger.WriteLine調用中使用ToString(),這是昂貴的,因爲它還創建了新的字符串(例如用於更改數字)。如何解決這個問題呢?有關調試

幾個點/問題/追蹤:

  • 我不想每包在Debugger.WriteLine IF語句或爲了使用預處理指令離開了調試的方法,因爲它將不可避免地導致不太可讀的代碼,並且它需要太多的輸入。

  • 我不想使用任何框架進行跟蹤/調試。我想嘗試自己編程。

  • 如果在發佈模式下編譯,Trace methods會被忽略嗎?如果是這樣,我的方法可能會有相似的表現嗎?

  • 隨着static String.Format method我可以這樣做:

    輸出=的String.Format( 「你現在{0}歲。」 歲);

這看起來不錯。這是我的ToString()問題的解決方案嗎?

+0

這種方法真的存在性能問題嗎? – harpo 2010-04-14 18:58:24

+0

@harpo:有很多不可變的字符串被創建。單次調用並不算太糟糕,但如果此方法輸出頻率足夠高,則會由於所有字符串對象分配而減慢速度。 – 2010-04-14 19:00:07

+0

它經常被調用。 – 2010-04-14 19:08:55

回答

3

使用StringBuilder來創建您的輸出字符串,而不是連接每個值。

而且您可以創建自己的自定義調試器(MyDbg)類,該類包含一個WriteLine成員,其內容可以用編譯指令包圍。它不會完全編譯出調試代碼,但會將您的MyDbg.WriteLine調用變爲空操作。

下面是類的速寫:

using System; 
using System.Text ; 

public static class MyDbg 
{ 
    public static void WriteLine(string str) // and some other params 
    { 
     #if DEBUG 

     StringBuilder sb = new StringBuilder(); 
     sb.Append(str); 
     // etc. appending other params as you see fit 
     #endif 
    } 
} 

OR

[Conditional("DEBUG")] 
public static class MyDbg 
{ 
    public static void WriteLine(string str) // and some other params 
    { 
     StringBuilder sb = new StringBuilder(); 
     sb.Append(str); 
     // etc. appending other params as you see fit 
    } 
} 

你會修改,以適合自己的道路的需求。而不是創建一個單獨的類,您可以創建一個成員方法,如果#if DEBUG /#endif內置在調試器中顯示其自己的狀態。

+1

我不相信StringBuilder會在這種情況下有所作爲。由於字符串是用單個語句組裝的,因此編譯器不會爲每個並置創建中間字符串。 (AFAIK) – harpo 2010-04-14 18:59:47

+0

@harpo:這是我從未聽說過的編譯器優化。據我所知,字符串操作是不可變的,任何連接或擴充都會創建一個新的連接,而不管它在哪裏使用。 – 2010-04-14 19:02:05

+0

harpo是對的:編譯器用string替換a + b + c.Concat(a,b,c) – 2010-04-14 19:12:58

0
  1. 您不需要包裝每一行。只需編寫包含Debug.WriteLine的幫助器方法,並通過標記(通常是布爾)將其打開/關閉。

  2. 即使在發佈模式下,跟蹤也會在您的代碼中。您可以對其進行配置,請參閱http://msdn.microsoft.com/en-us/library/system.diagnostics.tracelistener.aspx

  3. string.Format在內部調用參數的ToString(),因此沒有任何好處。

+0

1.我已經完成了。 2.,3.謝謝你的回答! – 2010-04-14 19:13:46

+0

關於(3),我認爲這與此無關,因爲無論如何,性能考慮在調試配置中通常都不是問題。 'string.Format'仍然具有提高代碼易讀性的好處(我會說,這與調試結伴而行)。 – stakx 2010-04-14 19:15:41

+0

stakx:我認爲它是相關的,因爲您可以在發佈代碼中啓用跟蹤,從而影響應用性能。 – 2010-04-14 21:07:35

2

對於日誌記錄有一個框架,如Log4net或企業庫。他們通過多種方式使日誌可配置。即使你想記錄。

HTH

1

使用string.Format(),預計產量將實際上只是從看代碼(恕我直言)變得更加容易辨認:

Debug.WriteLine(string.Format(
    "[Draw]InProgress[x,y] = {0:0.00}, {1:0.00}; pos = {2}x{3} -> {4}x{5}; ...", 
    x, y, 
    lastPosX, lastPosY, 
    posX, posY, 
    ...)); 
+0

謝謝,它看起來不錯! – 2010-04-14 19:20:07

4

使用反射我發現的Debug.WriteLine聲明本方式:

[Conditional("DEBUG")] 
public static void WriteLine(string message) 

這意味着在發佈模式下,所有對此方法的調用都將從代碼中消除。

例如這樣的代碼:

public static void Test(int a) 
{ 
    string b = Console.ReadLine(); 
    Debug.WriteLine(a + " " + b); 
    Console.WriteLine(a + " " + b); 
} 

在釋放模式編譯成:

public static void Test(int a) 
{ 
    Console.WriteLine(a + " " + Console.ReadLine()); 
} 
+0

+1; http://msdn.microsoft.com/en-us/library/aa288458(VS.71).aspx - 確認你所說的話的鏈接。 – 2010-04-14 19:25:14

1

我使用被定義一個日誌接口(ILogger),該得到的依賴注入到所有的類的圖案

public class MyClassThatLogs 
{ 
    public MyClassThatLogs(ILogger logger) 
    { 
     try 
     { 
      logger.Write("bla bla bla"); 
     } 
     catch(Exception ex) 
     { 
      logger.Write(ex); //overload of Write() that takes in an Exception 
     } 
    } 
} 

所以,當你新增了它,你可以通過一個'真正'的記錄器或模擬/假的

var mc = new MyClassThatLogs(new FakeLogger()); 

現在,您已經抽象了MyClassThatLogs類中需要了解的日誌記錄。基本的固體東西。因此,'top'(比如控制檯的main()方法)會讓IF DEBUG指令傳遞給記錄器的正確實現。

+0

謝謝你的建議!我正在考慮[有條件的(「FakeLogger」)],[有條件的(「MyLogger」)],...的類。也許它會像你的解決方案一樣靈活。記錄器的變化將是Visual Studio中更改模式的問題。 – 2010-04-14 20:07:19

+0

酷!我認爲重要的是讓類的依賴脫離出來......你的類不應該在乎如何實現日誌記錄,而應該聲明它需要記錄日誌。再次,這只是來自SOLID原則 - 控制和依賴注入的倒置。 – 2010-04-14 22:17:47