问题
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?
回答1:
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
.
回答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.
来源:https://stackoverflow.com/questions/12285370/net-why-is-disposing-of-standard-output-only-allowed-during-unit-tests