1

First of all, I want to point out that I do not really want to dispose of the standard output...I just want to know why I'm seeing the described behavior. I didn't write the bad code described.

I'm using .NET 4 for the unit tests and .NET 3.5 for the code being tested. I'm using MSTest for .NET 4 as my testing framework.

Recently I have been working with a library that was throwing errors due to the blunder of disposing of the standard error output. (See LibTiff.NET ReadDirectory is giving System.ObjectDisposedException Only During Unit Tests).

This is relatively what their code looked like:

using (TextWriter stderr = Console.Error)
{
    ...
}

Basically, when not running unit tests, the standard output is not disposed even if one specifically disposes of it, but when running unit tests, it is allowed.

Can anyone explain why the standard output is disposable only when doing so in the context of unit tests?

Community
  • 1
  • 1
bsara
  • 7,940
  • 3
  • 29
  • 47
  • 1
    Did you have more than one test doing this? – Reed Copsey Sep 05 '12 at 15:59
  • @ReedCopsey I still got the error when running a single test. – bsara Sep 05 '12 at 16:00
  • Whatever is, do not dispose the console stream. Just use it without the `using`, this is the right thing to do. – Marcelo De Zen Sep 05 '12 at 16:02
  • @ReedCopsey I've updated the question to answer your question for testing framework. – bsara Sep 05 '12 at 16:04
  • @devundef No offense, but did you really read my question? I wasn't asking how to best do this or what is wrong...I'm asking why I'm seeing certain results. – bsara Sep 05 '12 at 16:06
  • @Brandon, I do read your question. This error for sure is because the stream was disposed and is needed somewhere in the code (like pointed by Reed in his answer, the test framework uses the stream). What I meant was that is useless look for the error because the right thing to do is not use the `Console.Error` stream and dispose it. – Marcelo De Zen Sep 05 '12 at 16:10
  • What is the stack trace of the `ObjectDisposedException`? You should be able to dispose an object multiple times - the exception is only thrown if you try to "use" an object that is already disposed. It is not clear from your question when the disposed object is "reused". – Martin Liversage Sep 05 '12 at 16:13
  • What is the version of .net --make sure that on the IIS server you are running the same asp.net version. Also include some more info, like an error message. –  Sep 05 '12 at 16:01

2 Answers2

3

Calling a method on a disposed object will throw ObjectDisposedException. E.g.:

var textWriter = Console.Error;
textWriter.Dispose();
textWriter.WriteLine("Test");

The last line should throw an exception. Except it doesn't always to that.

If you peruse the BCL source code you can see that Console either uses a StreamWriter (really a synchronized stream writer) that is hooked up to either a "real" stream (e.g. the console error stream) or if that is not available to StreamWriter.Null.

The "real" StreamWriter is constructed in a special way so that it is not closeable. This means that even if you close it (or dispose it) it just continues to function as expected.

So if you have a "real" console stream you can close Console.Error as many times as you want without closing the underlying stream. Also you wont get any ObjectDisposedException.

If there is no "real" stream attached to Console.Error closing the StreamWriter will close the underlying stream (in this case Stream.Null) which doesn't exhibit the special non-closeable behavior, and if you try to use the StreamWriter later you will get an ObjectDisposedException.

The bottom line is that you can get a ObjectDisposedException if you close a console stream writer prematurely in an application that doesn't have a real console stream.

The information above also applies to Console.Out.

Martin Liversage
  • 104,481
  • 22
  • 209
  • 256
  • @Brandon: The best place to link to is my answer. I didn't read the information somewhere else. I looked at the BCL source code to learn some details about the `Console` class. – Martin Liversage Sep 06 '12 at 11:12
2

The problem is likely due to the fact that MSTest uses the standard output stream. In addition to writing timings into the stream, when you run tests, the standard output is actually stored and available in the test results. By disposing of the standard output stream, you're likely interfering with the testing framework's operation itself.

That being said, this is a bug - so your test is showing you something you shouldn't be doing in the first place.... Luckily, the library has corrected this error, so you should be good in the future.

Reed Copsey
  • 554,122
  • 78
  • 1,158
  • 1,373