无法为 StreamWriter 应用“using”的新语法

Unable to apply the new syntax of `using` for StreamWriter

MSDN about using 上出现了新语法。喜欢就开始应用了

而不是

using (MemoryStream memory = new MemoryStream())
{
  using (CryptoStream crypto = new CryptoStream(memory, transform, CryptoStreamMode.Write))
  {
    using (StreamWriter writer = new StreamWriter(crypto))
    {
      writer.Write(text);
    }
  }
}

我可以走了

using Aes aes = Aes.Create();
using ICryptoTransform transform = aes.CreateEncryptor(key, iv);
using MemoryStream memory = new MemoryStream();
using CryptoStream crypto = new CryptoStream(memory, transform, CryptoStreamMode.Write);
using (StreamWriter writer = new StreamWriter(crypto))
  writer.Write(text);

但是,我无法让最后一部分以新的方式工作。出于某种原因,StreamWriter 不允许我这样做。

using Aes aes = Aes.Create();
using ICryptoTransform transform = aes.CreateEncryptor(key, iv);
using MemoryStream memory = new MemoryStream();
using CryptoStream crypto = new CryptoStream(memory, transform, CryptoStreamMode.Write);
using StreamWriter writer = new StreamWriter(crypto);
writer.Write(text);

我真的不明白为什么。链接文章中可能有技术解释,因为他们讨论了要求和限制。遗憾的是,我根本看不出他们说的是什么,暗示的是什么。

根据 Skeety 的要求 - 完整的可重现样本。

public void Test()
{
  string text = "hakuna matata";
  string code = "1234567890abcdef";
  byte[] key = Encoding.ASCII.GetBytes(code);
  byte[] iv = key[..16];

  using Aes aes = Aes.Create();
  using ICryptoTransform transform = aes.CreateEncryptor(key, iv);
  using MemoryStream memory = new MemoryStream();
  using CryptoStream crypto = new CryptoStream(memory, transform, CryptoStreamMode.Write);

  using StreamWriter writer = new StreamWriter(crypto);
  writer.Write(text);
  //writer.Flush();

  //using (StreamWriter writer = new StreamWriter(crypto))
  //  writer.Write(text);

  string output = Convert.ToBase64String(memory.ToArray());
}

在您的旧代码下,您的所有资源,包括 StreamWriterCryptoStream,都在其 using 块的末尾隐式处理。处理后,任何待处理的内容都会刷新到 MemoryStream。因此,当您检查 MemoryStream 这些 using 块的末尾时,它会被正确填充。

在您的新代码中,新的 using 语法意味着资源仅在 enclosing 块的末尾处理——在本例中,父方法.因此,当您在同一方法中检查 MemoryStream 时,您是在 before StreamWriterCryptoStream 已被处置,因此 before 它们的内容已经刷新到 MemoryStream.

为了演示,在读取 MemoryStream 之前在 StreamWriter 上调用 Dispose 将恢复正确的行为:

using StreamWriter writer = new StreamWriter(crypto);
writer.Write(text);
writer.Dispose()
string output = Convert.ToBase64String(memory.ToArray());

也就是说,我不建议这样做,因为您将显式 Dispose 调用与 using.

生成的隐式调用混合在一起

或者,您可以从 outer 方法中使用 MemoryStream,从而确保 inner 方法在执行结束时释放其资源:

public void Test()
{
     var memory = TestInner();
     string output = Convert.ToBase64String(memory.ToArray());
}

private MemoryStream TestInner()
{
    string text = "hakuna matata";
    string code = "1234567890abcdef";
    byte[] key = Encoding.ASCII.GetBytes(code);
    byte[] iv = key[..16];

    using Aes aes = Aes.Create();
    using ICryptoTransform transform = aes.CreateEncryptor(key, iv);
    using MemoryStream memory = new MemoryStream();
    using CryptoStream crypto = new CryptoStream(memory, transform, CryptoStreamMode.Write);

    using StreamWriter writer = new StreamWriter(crypto);
    writer.Write(text); 

    return memory;
}

但是,在这种情况下,为了清楚起见,我更愿意使用旧的 using 块。