try catch finally块的作用是什么?

3
使用finally和不使用finally的区别是什么?
void ReadFile(int index)
{
    // To run this code, substitute a valid path from your local machine
    string path = @"c:\users\public\test.txt";
    System.IO.StreamReader file = new System.IO.StreamReader(path);
    char[] buffer = new char[10];
    try
    {
        file.ReadBlock(buffer, index, buffer.Length);
    }
    catch (System.IO.IOException e)
    {
        Console.WriteLine("Error reading from {0}. 
           Message = {1}", path, e.Message);
    }
    finally
    {
        if (file != null)
        {
            file.Close();
        }
    }
    // Do something with buffer...
}

不使用它?

void ReadFile(int index)
{
    // To run this code, substitute a valid path from your local machine
    string path = @"c:\users\public\test.txt";
    System.IO.StreamReader file = new System.IO.StreamReader(path);
    char[] buffer = new char[10];
    try
    {
        file.ReadBlock(buffer, index, buffer.Length);
    }
    catch (System.IO.IOException e)
    {
        Console.WriteLine("Error reading from {0}. 
            Message = {1}", path, e.Message);
    }

    if (file != null)
    {
        file.Close();
    }

    // Do something with buffer...
}

3
捕获块可能重新抛出错误,引发新的错误等,这将绕过 finally 的关闭。请参见此处 - https://dev59.com/PnVD5IYBdhLWcg3wNY1Z - StuartLC
我知道肯定有人会比我更快地打出答案,但你考虑过自己引发一个IOException并看看区别吗? - ChaosPandion
4个回答

6

无论是否抛出异常或抛出什么异常,前一个示例都会运行file.Close()

只有在未抛出异常或抛出System.IO.IOException时,后一个示例才会运行。


是的,我以前做不到,直到现在才上线。 - bevacqua

3
区别在于,如果您不使用 finally 并且抛出的异常不是 IOException,则您的应用程序将泄漏文件句柄,因为永远不会到达 .Close 行。
个人而言,在处理可释放资源(例如流)时,我总是使用 using 块:
try
{
    using (var reader = File.OpenText(@"c:\users\public\test.txt"))
    {
        char[] buffer = new char[10];
        reader.ReadBlock(buffer, index, buffer.Length);
         // Do something with buffer...
    }
}
catch (IOException ex)
{
    Console.WriteLine("Error reading from {0}. Message = {1}", path, e.Message);
}

这样我就不必担心正确地处理它们。try/finally的事情由编译器处理,我可以专注于逻辑。


是的,我只是复制并粘贴了一个示例,如果我没有指定到仅限于IOExceptions会怎样? - bevacqua

1

你的 catch 块本身可能会抛出异常(考虑当 path 是 null 引用时的情况)。或者在 try 块中抛出的异常不是 System.IO.IOException,因此它没有被处理。除非使用 finally,否则在这两种情况下文件句柄都不会被关闭。


0
在您的情况下,什么都不需要做。如果让异常从catch块中抛出,那么finally部分将会运行,但另一种变化则不会。

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