c#如果异常被捕获,它会到达我的返回语句吗?

本文关键字:我的 返回 语句 异常 如果 | 更新日期: 2023-09-27 18:15:22

在系统中。IO有一个函数:字符串文件。ReadAllText(string path);

我正试图写一个函数,将调用文件。ReadAllText,处理所有可能的异常,返回true/false并存储错误信息。

我有这个:

public static class FileNoBS
{
    public static bool ReadAllText( string path, out string text, out string errorMessage )
    {
        errorMessage = null;
        text = null;
        bool operationSuccessful = false;
        try
        {
            text = System.IO.File.ReadAllText( path );
            operationSuccessful = true;
        }
        catch ( ArgumentNullException e )
        {
            errorMessage = "Internal software error - argument null exception in FileNoBs.ReadAllText'nMessage: " + e.Message;
        }
        catch ( ArgumentException e )
        {
            errorMessage = "Internal software error - path is a zero-length string, contains only white space, or contains one or more invalid characters as defined by InvalidPathChars in FileNoBs.ReadAllText.'nMessage: " + e.Message;
        }
        catch ( PathTooLongException e )
        {
            errorMessage = "The specified path was too long.'nMessage: " + e.Message;
        }
        catch ( DirectoryNotFoundException e )
        {
            errorMessage = "The specified directory was not found.'nMessage: " + e.Message;
        }
        catch ( FileNotFoundException e )
        {
            errorMessage = "The file specified in path was not found.'nMessage: " + e.Message;
        }
        catch ( IOException e )
        {
            errorMessage = "An I/O error occurred while opening the file.'nMessage: " + e.Message;
        }
        catch ( UnauthorizedAccessException e )
        {
            errorMessage = @"UnauthorizedAccessException
path specified a file that is read-only.
-or-
This operation is not supported on the current platform.
-or-
path specified a directory.
-or-
The caller does not have the required permission.'nMessage: " + e.Message;
        }
        catch ( NotSupportedException e )
        {
            errorMessage = "path is in an invalid format.'nMessage: " + e.Message;
        }
        catch ( SecurityException e )
        {
            errorMessage = "You do not have the required permission.'nMessage: " + e.Message;
        }
        return operationSuccessful;
    }
}

我不明白控制流如何与返回值的函数一起运行。比如UnauthorizedAccessException被捕获,errorMessage被设置为

    errorMessage = "You do not have the required permission..."

我知道finally每次都会被执行,但是编译器不会让我在finally块内执行return。我还能不能回来?

另一个问题是如何简化这一点,同时仍然遵循官方指导方针:"一般来说,你应该只捕捉那些你知道如何恢复的异常。"

我害怕从File类(Move, Copy, Delete, ReadAllText, WriteAllText)和Directory类中遍历所有我需要的函数,然后做所有这些长代码块,只是为了捕获所有我不关心的异常,而不是捕获太多异常,因为微软说这很糟糕。

谢谢。

编辑:我得到这样的评论,这不是处理异常,这是"别的东西"。

我是客户端为我的代码,我想做这样的事情:

if ( !FileNoBS.ReadAllText( path, text, errorMessage ) ) {
   MessageBox.Show( errorMessage );
   return;
}
// continue working with all errors taken care of - don't care for whatever reason file wasn't opened and read, user is notified and I am moving on with my life

c#如果异常被捕获,它会到达我的返回语句吗?

由于在try块或catch块中没有返回,因此将到达您的返回。

一般来说,您只想捕获您预期可能发生的异常,并有处理它们的方法。例如,您可能希望处理从给定路径中找不到的文件,并返回一个默认文件。您应该允许其他异常不被捕获,这样您就知道发生了意想不到的事情,而不是通过捕获所有异常来隐藏它。

正如我在评论中所说的,您最好在更高的级别处理异常并简单地显示异常消息,而不是手动设置每个消息。我认为在这种情况下,来自异常的消息将具有足够的描述性。

    public static class FileNoBS
    {
        public static string ReadAllText(string path)
        {
            return System.IO.File.ReadAllText( path );
        }   
    }

,然后在应用程序的更高级别像这样使用它。我通常有一个通用处理程序来处理所有应用程序异常,并记录它们,并在必要时显示一个消息框。

    try
    {
        var text = FileNoBS.ReadAllText("file.ext");
    }
    catch(Exception e)
    {
    Console.WriteLine(e.Message);
    }

与其捕捉异常,不如尝试避免导致这些异常被抛出的情况。在您的情况下,您应该在调用ReadAllText

之前进行一些输入验证。
  • 永远不要接受null路径——你知道这会导致异常,所以在它发生之前处理它
  • 永远不接受指向不存在的文件的路径-在调用
  • 之前使用File.Exists(path)
  • 永远不接受格式错误的路径,例如空字符串或无效字符-这将导致异常

这些测试应在输入源处进行。也就是说,如果用户键入它们,则在使用它们之前对它们进行验证。如果它们来自数据库或其他地方,请在使用前进行验证。如果不是用户输入,它们都是系统错误的迹象,应该被视为系统错误,而不是用户应该担心的事情。

安全异常可能在某种程度上难以预先测试,并且在许多情况下,获得违规是异常,因此获得异常是完全可以的。当然,它不应该使程序崩溃,而是通过向用户发送错误消息来处理(如果它是基于用户输入的,如果是系统生成的数据导致的,则它是应该在代码级别修复的系统错误的标识)。在调用发生的地方执行此操作通常比在某些库方法中执行更合适。

对于IOExceptions,它们可以放入两个桶中。一次可恢复(通常是重试),一次不可恢复。至少要给用户关于异常的反馈,这样用户就可以选择重试。

一个非常普遍的规则应该是纠错逻辑的一部分,即永远不要在系统中浮动无效数据。确保所有对象都管理不变量(工具可用于此,例如代码契约)。当接收到来自用户(或其他系统)的无效输入时拒绝它们,而不是在它们导致异常时拒绝它们。

如果你做了所有的输入验证,仍然有例如ArgumentNullException,那么这就指出了程序逻辑中的错误,这是你希望能够在测试中轻松找到并在发布bug之前纠正的错误。你不应该试图掩盖这个错误。

如果没有其他错误发生,则是。

我想在结尾加上:

catch (Exception e)
{
    errormessage = "An unexpected error has occured.";
}
return operationSuccessful;

虽然,这将始终返回成功,即使你得到一个错误。我不确定这是否是您想要的,或者您的变量是否命名不当。

return语句将在代码中出现任何异常的情况下被调用,在它被放置在程序结束之前退出。

我建议将一个异常处理程序与高级异常类型(如' exception '类型本身)放在一起,并打印或记录异常消息。在每个方法中指定如此多的异常处理程序将花费大量的精力,这些精力实际上应该放在方法本身中。

        try
        {
            return ReadAllText("path", "text", "error");
        }
        catch (Exception exception)
        {
            Console.WriteLine(exception);
        }
        return false;

如果方法被调用,它将立即返回,否则异常将被打印/记录,方法将返回false。

但是,在某些情况下,您可以在您认为有益的情况下提及几个显式异常处理程序。

是将返回值

但是,最好在finally语句中处理return的值。

如果在任何情况下都希望返回operationsuccess值,那么在catch块之后写入finally块,如下所示,

finally
{
  return operationSuccessful;
}