Why call to `StreamReader.ReadAsync` with `count` parameter 0 advances `Position` of underlying stream?

414 views Asked by At

While working with the System.IO.StreamReader class of the .NET Framework I noticed what seems to me to be strangely inconsistent behavior:

Calling the Read(Char[], Int32, Int32) method and passing 0 for the count parameter (i.e. read zero bytes), the Position property on the underlying Stream object is 0, as expected.

However calling the ReadAsync(Char[], Int32, Int32) method in the same way, the Position property on the underlying Stream object is not zero, as I would expected, but the length of the contents of the stream; I would expect it to be zero as in the synchronous test case.

Is this a bug in the framework implementation or am I missing something?

The following test code demonstrates:

using Microsoft.VisualStudio.TestTools.UnitTesting;
using System.IO;
using System.Threading.Tasks;

namespace ExplorationTesting
{

    [TestClass]
    public class TestStreamReader
    {

        public static Stream CreateStream(string fromString)
        {
            var stream = new MemoryStream();
            var writer = new StreamWriter(stream);
            writer.Write(fromString);
            writer.Flush();
            stream.Position = 0;
            return stream;
        }

        [TestMethod] // Test Passes
        public void TestReadingZeroBytesFromStreamReader_StreamPositionIsZero()
        {
            using (Stream stream = CreateStream("Foo"))
            using (StreamReader reader = new StreamReader(stream)) {
                Assert.AreEqual(0, stream.Position);
                char[] buffer = new char[] { };
                var r = reader.Read(buffer, 0, 0);
                Assert.AreEqual(0, r);
                Assert.AreEqual(0, stream.Position);
            }
        }

        [TestMethod] // Test Fails
        public async Task TestReadingZeroBytesFromStreamReader_StreamPositionIsZero_Async()
        {

            using (Stream stream = CreateStream("Foo"))
            using (StreamReader reader = new StreamReader(stream)) {
                Assert.AreEqual(0, stream.Position);
                char[] buffer = new char[] { };
                var r = await reader.ReadAsync(buffer, 0, 0);
                Assert.AreEqual(0, r);
                Assert.AreEqual(0, stream.Position); // Assert.AreEqual failed. Expected:<0>. Actual:<3>. 
            }
        }
    }
}
0

There are 0 answers