31

I'm often frustrated by the System.Diagnostics.Debug.Write/WriteLine methods. I would like to use the Write/WriteLine methods familiar from the TextWriter class, so I often write

Debug.WriteLine("# entries {0} for connection {1}", countOfEntries, connection);

which causes a compiler error. I end up writing

Debug.WriteLine(string.Format("# entries {0} for connection {1}", 
    countOfEntries, connection));

which is really awkward.

Does the CLR have a class deriving from TextWriter that "wraps" System.Debug, or should I roll my own?

John Källén
  • 7,551
  • 31
  • 64

4 Answers4

39

The function Debug.Print lets you use formatting and arguments.

If you'd prefer to use a TextWriter interface, use the following wrapper class:

public class DebugTextWriter : StreamWriter
{
    public DebugTextWriter()
        : base(new DebugOutStream(), Encoding.Unicode, 1024)
    {
        this.AutoFlush = true;
    }

    sealed class DebugOutStream : Stream
    {
        public override void Write(byte[] buffer, int offset, int count)
        {
            Debug.Write(Encoding.Unicode.GetString(buffer, offset, count));
        }

        public override bool CanRead => false;
        public override bool CanSeek => false;
        public override bool CanWrite => true;
        public override void Flush() => Debug.Flush();

        public override long Length => throw bad_op;
        public override int Read(byte[] buffer, int offset, int count) => throw bad_op;
        public override long Seek(long offset, SeekOrigin origin) => throw bad_op;
        public override void SetLength(long value) => throw bad_op;
        public override long Position
        {
            get => throw bad_op;
            set => throw bad_op;
        }

        static InvalidOperationException bad_op => new InvalidOperationException();
    };
}
Glenn Slayden
  • 17,543
  • 3
  • 114
  • 108
17

Here's a quick go at a TextWriter wrapper for System.Diagnostics.Debug:

class TextWriterDebug : System.IO.TextWriter
{
    public override System.Text.Encoding Encoding
    {
        get { return System.Text.Encoding.Default; }
    }

    //public override System.IFormatProvider FormatProvider
    //{ get; }
    //public override string NewLine
    //{ get; set; }

    public override void Close()
    {
        System.Diagnostics.Debug.Close();
        base.Close();
    }

    protected override void Dispose(bool disposing)
    {
        base.Dispose(disposing);
    }

    public override void Flush()
    {
        System.Diagnostics.Debug.Flush();
        base.Flush();
    }

    public override void Write(bool value)
    {
        System.Diagnostics.Debug.Write(value);
    }

    public override void Write(char value)
    {
        System.Diagnostics.Debug.Write(value);
    }

    public override void Write(char[] buffer)
    {
        System.Diagnostics.Debug.Write(buffer);
    }

    public override void Write(decimal value)
    {
        System.Diagnostics.Debug.Write(value);
    }

    public override void Write(double value)
    {
        System.Diagnostics.Debug.Write(value);
    }

    public override void Write(float value)
    {
        System.Diagnostics.Debug.Write(value);
    }

    public override void Write(int value)
    {
        System.Diagnostics.Debug.Write(value);
    }

    public override void Write(long value)
    {
        System.Diagnostics.Debug.Write(value);
    }

    public override void Write(object value)
    {
        System.Diagnostics.Debug.Write(value);
    }

    public override void Write(string value)
    {
        System.Diagnostics.Debug.Write(value);
    }

    public override void Write(uint value)
    {
        System.Diagnostics.Debug.Write(value);
    }

    public override void Write(ulong value)
    {
        System.Diagnostics.Debug.Write(value);
    }

    public override void Write(string format, object arg0)
    {
        System.Diagnostics.Debug.Write(string.Format(format, arg0));
    }

    public override void Write(string format, params object[] arg)
    {
        System.Diagnostics.Debug.Write(string.Format(format, arg));
    }

    public override void Write(char[] buffer, int index, int count)
    {
        string x = new string(buffer, index, count);
        System.Diagnostics.Debug.Write(x);
    }

    public override void Write(string format, object arg0, object arg1)
    {
        System.Diagnostics.Debug.Write(string.Format(format, arg0, arg1));
    }

    public override void Write(string format, object arg0, object arg1, object arg2)
    {
        System.Diagnostics.Debug.Write(string.Format(format, arg0, arg1, arg2));
    }

    public override void WriteLine()
    {
        System.Diagnostics.Debug.WriteLine(string.Empty);
    }

    public override void WriteLine(bool value)
    {
        System.Diagnostics.Debug.WriteLine(value);
    }

    public override void WriteLine(char value)
    {
        System.Diagnostics.Debug.WriteLine(value);
    }

    public override void WriteLine(char[] buffer)
    {
        System.Diagnostics.Debug.WriteLine(buffer);
    }

    public override void WriteLine(decimal value)
    {
        System.Diagnostics.Debug.WriteLine(value);
    }

    public override void WriteLine(double value)
    {
        System.Diagnostics.Debug.WriteLine(value);
    }

    public override void WriteLine(float value)
    {
        System.Diagnostics.Debug.WriteLine(value);
    }

    public override void WriteLine(int value)
    {
        System.Diagnostics.Debug.WriteLine(value);
    }

    public override void WriteLine(long value)
    {
        System.Diagnostics.Debug.WriteLine(value);
    }

    public override void WriteLine(object value)
    {
        System.Diagnostics.Debug.WriteLine(value);
    }

    public override void WriteLine(string value)
    {
        System.Diagnostics.Debug.WriteLine(value);
    }

    public override void WriteLine(uint value)
    {
        System.Diagnostics.Debug.WriteLine(value);
    }

    public override void WriteLine(ulong value)
    {
        System.Diagnostics.Debug.WriteLine(value);
    }

    public override void WriteLine(string format, object arg0)
    {
        System.Diagnostics.Debug.WriteLine(string.Format(format, arg0));
    }

    public override void WriteLine(string format, params object[] arg)
    {
        System.Diagnostics.Debug.WriteLine(string.Format(format, arg));
    }

    public override void WriteLine(char[] buffer, int index, int count)
    {
        string x = new string(buffer, index, count);
        System.Diagnostics.Debug.WriteLine(x);

    }

    public override void WriteLine(string format, object arg0, object arg1)
    {
        System.Diagnostics.Debug.WriteLine(string.Format(format, arg0, arg1));
    }

    public override void WriteLine(string format, object arg0, object arg1, object arg2)
    {
        System.Diagnostics.Debug.WriteLine(string.Format(format, arg0, arg1, arg2));
    }

} // Ends class TextWriterDebug 
WaffleSouffle
  • 3,293
  • 2
  • 28
  • 27
  • Did you create this wrapper manually? IF not, what tool did you use to auto-generate the code? – sammarcow Jan 30 '13 at 18:06
  • @sammarcow I did something like taking the meta-data generated outline of TextWriter in Visual Studio, cutting and pasting it, and going from there. 'Twas a while ago. – WaffleSouffle Feb 04 '13 at 10:49
  • 1
    This is nice. One point to consider: I'm not sure I'd want to close out all Debug trace listeners when this TextWriter is closed, however. – codekaizen Jun 19 '17 at 17:43
8

Do you particularly need a whole TextWriter? While this is somewhat "quick and dirty" I suspect a static class with just a few methods would do perfectly well:

public static class DebugEx
{
    [Conditional("DEBUG")]
    public static void WriteLine(string format, params object[] args)
    {
        Debug.WriteLine(string.Format(format, args));
    }
}

or something similar.

Mind you, I'd personally look at something like log4net to give more control over the output.

MasterMastic
  • 20,711
  • 12
  • 68
  • 90
Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
2

With C# 6 and later versions string interpolation is the answer for most formatting of strings. So the example would look like:

Debug.WriteLine($"# entries {countOfEntries} for connection {connection}");
Fabian
  • 1,100
  • 11
  • 14