为何未手动释放StreamWriter时MemoryStream.ToArray()返回空数组
问题原因解析
- 核心原因和
StreamWriter的缓冲区机制、C# 8+using var的释放时机有关 - 首先
StreamWriter写入内容时,数据会先存到内部缓冲区,默认缓冲区大小为4KB,只有缓冲区满、手动调用Flush()/Dispose()时,才会把缓冲区内容写入底层绑定的MemoryStream中。你写入的内容小于缓冲区阈值时,不会自动触发刷写操作。 - 你使用的是C# 8引入的
using var声明式语法,这种语法绑定的资源释放时机是变量离开当前作用域时,也就是整个方法执行完毕、return语句执行完成之后,才会调用StreamWriter的Dispose方法。你删除手动sw.Dispose()代码后,执行ms.ToArray()时StreamWriter还未被释放,缓冲区数据还没写入MemoryStream,自然拿到的就是空数组。 - 你手动调用
sw.Dispose()时,会立刻触发缓冲区刷写,把所有内容写入MemoryStream,所以能拿到正确的字节数组。
正确优化写法
你不需要手动调用Dispose,可以用两种方案解决问题:
- 调用
Flush手动刷写缓冲区
public static byte[] GetByteArray(List<MyModel> models) { using var ms = new MemoryStream(); using var sw = new StreamWriter(ms); foreach (var model in models) { sw.WriteLine($"{model.Id},{model.Name}"); } sw.Flush(); // 手动刷写缓冲区到MemoryStream return ms.ToArray(); }
- 使用块级
using,保证StreamWriter在读取MemoryStream前就完成释放
public static byte[] GetByteArray(List<MyModel> models) { using var ms = new MemoryStream(); // 块级using,代码块结束时自动释放StreamWriter using (var sw = new StreamWriter(ms)) { foreach (var model in models) { sw.WriteLine($"{model.Id},{model.Name}"); } } // 此处StreamWriter已释放,缓冲区已刷入MemoryStream return ms.ToArray(); }
内容的提问来源于stack exchange,提问作者Viktor Husiev
相关产品推荐
相关产品推荐

