我知道如何使用try-catch-finally。但是我没有得到使用finally
的进展,因为我总是可以将代码放在try-catch块之后。
有没有明确的例子?
答案 0 :(得分:4)
你需要一个终极因为你不应该总是有一个问题:
void M()
{
var fs = new FileStream(...);
try
{
fs.Write(...);
}
finally
{
fs.Close();
}
}
上述方法没有捕获使用fs
的错误,将它们留给调用者。但它应该总是关闭流。
请注意,这种代码通常会使用using() {}
块,但这只是try / finally的简写。完成:
using(var fs = new FileStream(...))
{
fs.Write(...);
} // invisible finally here
答案 1 :(得分:4)
它几乎总是用于清理,通常隐含地通过using
语句:
FileStream stream = new FileStream(...);
try
{
// Read some stuff
}
finally
{
stream.Dispose();
}
现在这 等同于
FileStream stream = new FileStream(...);
// Read some stuff
stream.Dispose();
因为“读取一些东西”代码可能抛出异常或可能返回 - 但是它完成后,我们想要处理流。
所以finally
块通常用于某种资源清理。但是,在C#中,它们通常是通过using
语句隐含的:
using (FileStream stream = new FileStream(...))
{
// Read some stuff
} // Dispose called automatically
finally
块在Java中比在C#中更常见,正是因为using
语句。我很少在C#中编写自己的finally
块。
答案 2 :(得分:3)
try
{
DoSomethingImportant();
}
finally
{
ItIsRidiculouslyImportantThatThisRuns();
}
当你有一个finally块时,其中的代码保证在try退出时运行。如果将代码放在try / catch之外,则情况并非如此。一个更常见的例子是当您使用using
语句时使用的一次性资源。
using (StreamReader reader = new StreamReader(filename))
{
}
扩展为
StreamReader reader = null;
try
{
reader = new StreamReader(filename);
// do work
}
finally
{
if (reader != null)
((IDisposable)reader).Dispose();
}
这确保即使在try
期间发生异常的情况下也会处置和释放所有非托管资源。
*请注意,有些情况下控件不会退出try,并且finally实际上不会运行。举个简单的例子,PowerFailureException
。
答案 3 :(得分:2)
即使在以下情况下,finally
块中的代码也会被执行:
return
或try
块中有catch
个语句
或强> catch
块重新抛出异常示例:强>
public int Foo()
{
try
{
MethodThatCausesException();
}
catch
{
return 0;
}
// this will NOT be executed
ReleaseResources();
}
public int Bar()
{
try
{
MethodThatCausesException();
}
catch
{
return 0;
}
finally
{
// this will be executed
ReleaseResources();
}
}
答案 4 :(得分:2)
更新:这实际上不是一个好的答案。另一方面,也许 是一个很好的答案,因为它说明了finally
成功的完美示例,其中开发人员(即我)可能无法确保正确清理。在下面的代码中,考虑抛出异常其他而不是SpecificException
的情况。然后第一个例子仍将执行清理,而第二个例子仍然不会,即使开发人员可能认为“我抓住了异常并处理了它,所以后续代码肯定会运行。”
每个人都有理由在没有 try
的情况下使用finally
/ catch
。使用一个catch
仍然有意义,即使您正在抛出异常。考虑要返回值的情况*。
try
{
DoSomethingTricky();
return true;
}
catch (SpecificException ex)
{
LogException(ex);
return false;
}
finally
{
DoImportantCleanup();
}
上述没有 a finally
的替代方案(在我看来)可读性较差:
bool success;
try
{
DoSomethingTricky();
success = true;
}
catch (SpecificException ex)
{
LogException(ex);
success = false;
}
DoImportantCleanup();
return success;
*我确实认为try
/ catch
/ finally
的更好示例是在重新抛出异常时(使用{{在throw
块中,1}},不是 throw ex
- 但这是另一个主题,因此catch
是必要的,因为finally
没有代码try
1}} / catch
无法运行。这通常通过using
资源上的IDisposable
语句来完成,但情况并非总是如此。有时,清理不是专门的Dispose
电话(或只是Dispose
电话)。
答案 5 :(得分:1)
您不一定会将其用于例外情况。您可能需要try/finally
在块中的每个return
之前执行一些清理。
答案 6 :(得分:1)
无论是否获得错误,都始终执行finally块。它通常用于清理目的。
对于你的问题,Catch的一般用法是将错误抛回调用者,在这种情况下,代码最终仍会执行。
答案 7 :(得分:0)
即使在catch块中重新抛出异常,也会始终执行finally块。
答案 8 :(得分:0)
我不确定它是如何在c#中完成的,但在Delphi中,你会经常发现“终于”。关键字是手动内存管理。
MyObject := TMyObject.Create(); //Constructor
try
//do something
finally
MyObject.Free();
end;
答案 9 :(得分:0)
如果catch块中发生异常(或重新抛出),catch之后的代码将不会被执行 - 相反,finally中的代码仍将被执行。
此外,当使用return退出方法时,甚至会执行finally中的代码。
最后在处理需要关闭的文件等外部资源时非常方便:
Stream file;
try
{
file = File.Open(/**/);
//...
if (someCondition)
return;
//...
}
catch (Exception ex)
{
//Notify the user
}
finally
{
if (file != null)
file.Close();
}
但请注意,在此示例中,您还可以使用使用:
using (Stream file = File.Open(/**/))
{
//Code
}
答案 10 :(得分:0)
例如,在此过程中您可以禁用WinForm ...
try
{
this.Enabled = false;
// some process
}
catch(Exception ex)
{
MessageBox.Show(ex.Message);
}
finally
{
this.Enabled = true;
}