空的 "using" 代码块

6
已经有人在这里确定了空的 using 块不是重写 Dispose() 的适当方式,但下面的情况呢?
这种情况是否可以使用空的 using 块?
try
{
    using (File.OpenRead(sourceFile)) { }
}
catch (FileNotFoundException)
{
    error = "File not found: " + sourceFile;
}
catch (UnauthorizedAccessException)
{
    error = "Not authorized to access file: " + sourceFile;
}
catch (Exception e)
{
    error = "Error while attempting to read file: " + sourceFile + ".\n\n" + e.Message;
}

if (error != null)
    return error;

System.Diagnostics.Process.Start(sourceFile);

你只是在检查是否可以访问和读取文件,而不需要实际内容吗? - Michael McGriff
@Dan 上下文几乎总是相关的 :) 为什么不尝试启动进程并在那里捕获任何异常呢? - Michael McGriff
@MichaelMcGriff Process.Start不会像OpenRead一样抛出相同的异常,因此很难确定出了什么问题。 - Dan Bechard
1
如果你有评论的话,我会没问题。否则,你可以使用这个模式。 - Conrad Frix
@ConradFrix 除了 IOException 可能会抛出许多其他异常。 - Dan Bechard
显示剩余3条评论
2个回答

3

在一个空的using块中使用try语句并不是合法的用法。

你可以像这样简单地编写try语句:

try
{
    File.OpenRead(sourceFile).Close();
}

要么OpenRead()会成功并返回一个流,你必须关闭它(或者释放资源,但是我认为用.Close()更能表达你的意图),要么它会抛出异常并且不会返回任何东西。
因此,你总是可以关闭返回的值。
(我假设你只是在检查读取权限之后再做其他事情。但是请注意,你可能在这个检查和实际打开文件之间存在竞争条件,因为文件的可访问性可能会发生变化。虽然这在实践中很少发生,但你应该知道这种可能性。)

但是如果 OpenRead 抛出异常,它就不会被关闭。 - Tim Schmelter
如果OpenRead抛出异常,它就没有被打开,因此也没有需要关闭的内容。 - Dan Bechard
如果OpenRead()抛出异常,那么文件没有被打开,并且它不会返回任何内容。 - Matthew Watson
@MatthewWatson:啊,好的,但就我个人而言,我觉得这不太易读。一眼看上去并不明显,这可能会导致资源泄露。这就是为什么我更喜欢在这里使用using(或try-catch-finally)。我还会使用using (MethodThatReturnsDisposable()){ },因为方法的执行可能很重要,但我不想消耗返回的可处理对象。 - Tim Schmelter
@TimSchmelter 然而,这确实应该是显然的——你应该知道 File.OpenRead() 只返回非空值。如果你知道这一点,你也应该知道你总是可以安全地关闭它。如果你不知道,那么在使用它之前,你是否会检查它的返回值是否为 null?因为如果你说 OpenRead() 不可能返回 null 不明显,那么你可能会编写检查返回值是否为 null 的代码……就像 Tigran 在他上面的代码示例中所做的那样。 - Matthew Watson
1
@MatthewWatson:我没有说它不能为 null 不明显,我是说我必须仔细考虑才能注意到只有在没有异常并且对象不为 null 时,这将始终关闭。现在显然了,是的。我也喜欢 using 的原因之一是它不像 Close 这样的方法需要考虑 null 还是非 null。意图很清楚,调用方法,不对返回的对象进行任何操作,确保它总是被处理掉。 - Tim Schmelter

-1

使用空的using块没有太多意义,因为你可以在catch链的末尾添加finally并在那里处理Dispose

FileStream fs;
try {

    fs = File.OpenRead(sourceFile); 
}
catch(..) {
}
catch(..) {
}
catch(..) {
}
finally {

  if(fs !=null) {
      fs.Close();
      fs.Dispose();

  }
}

1
这似乎仍然非常无意义,因为他似乎只是想查看文件是否存在并且他是否有访问权限。不是使用OpenRead的好方法。 - Dave Zych
@DaveZych:看起来这不仅仅是用于检查文件是否存在。在这种情况下,您还可以获得有关问题原因的可能反馈。 - Tigran
@DaveZych 它检查任何可能阻止用户读取文件的错误,而不仅仅是 File.Exists() - Dan Bechard
请注意,除非您将“fs”初始化为null,否则此代码实际上不会编译。 - Matthew Watson
@MatthewWatson:是的,而且你不能使用catch(..)。这只是一个伪代码,用于提供思路。 - Tigran

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接