为什么在 StreamReader.Read 周围使用 using() {} 允许之后删除文件?

Why using using() {} around StreamReader.Read allows the file to be deleted afterwards?

所以我正在为一个学校项目尝试 Windows 表格,并将 运行 保留在错误中:

System.IO.IOException('The process cannot access the file 'C:\XXXX\YYYY.txt' because it is being used by another process.'

尝试通过 button_click 事件删除文件 (File.Delete(path);) 时。

事实证明,当我更改以下方法时:

private void updateTxt(){
  String tempStore = "";
  iDLbl1.Text = "ID:" + id;//iDLbl1 is ID Label 1
  try
  {
      StreamReader Reader = new StreamReader(path);
      while (!Reader.EndOfStream)
        { tempStore += Reader.ReadLine() + "\n"; }
  }
  catch { noIDLbl.Visible = true; }
  rTxtBox.Text = tempStore;//rTxtBox is Rich Text Box
} 

private void updateTxt(){
    String tempStore = "";
    iDLbl1.Text = "ID:" + id;//iDLbl1 is ID Label 1
    try
    {
        using(StreamReader Reader = new StreamReader(path))
        {
            while (!Reader.EndOfStream)
            { tempStore += Reader.ReadLine() + "\n"; }
        }

    }
    catch { noIDLbl.Visible = true; }
    rTxtBox.Text = tempStore;//rTxtBox is Rich Text Box
}

异常停止弹出。 虽然代码有效,但我根本不知道是什么原因造成的......逻辑似乎不适合我,所以有人知道为什么会发生这种情况或有更合乎逻辑的解决方案吗?如果需要请寻求澄清,这是构造函数以防万一:

public FindID(String ID)
{
    id = ID;
    path = @"C:\XXXX\YYYY\"+ID+".txt";
    InitializeComponent();
    updateTxt();
}

在第二个代码中,一旦您的代码块执行,StreamReader 将被释放。由于 StreamReader 将被释放,文件未被当前进程锁定。

在您的第一个代码中,您可以通过在代码末尾处理它们来执行相同的操作。

在您的第一种方法中,由于您没有 Close()ing 或 Dispose()ing 您的 StreamReader,关联的文件句柄将保留到 StreamReader由垃圾收集器收集,这可能是许多秒,甚至几分钟后(请不要试图控制或影响 GC)。

在您的第二种方法中,using 范围在范围的末尾处理(并关闭)StreamReader(与 using 匹配的结束 }) ,这是使用实现 IDisposable 的任何 class 时的正确做法。然后释放文件的所有句柄,允许删除文件。 using 块也有 try / finally 块的保证,所以即使有 IO Exception:

也会调用 Dispose
using(StreamReader Reader = new StreamReader(path)) // try {StreamReader Reader = ...}
{
     ...
} <- equivalent to finally {Reader.Dispose();}

但是,由于您似乎只想立即实现以行分隔的文本文件中的所有行,因此您可以使用 File.ReadAllLines 一步完成此操作 - 即根本不需要 StreamReader :

var tempStore = string.Join(Environment.NewLine, File.ReadAllLines(path));