关于C#:C# – 这是一种简化System.IO.File.ReadAllText生成的异常的好方法

C# - is this good practice to simplify exceptions generated by System.IO.File.ReadAllText

显然,许多应用程序需要处理文件并向用户显示错误。然而,system.io.file类的memebers抛出了许多异常。这些仅用于readAllText:

  • 参数异常
  • ArgumentNullException
  • 路径工具异常
  • 目录未找到异常
  • 异常
  • 未授权访问异常
  • 文件未找到异常
  • 冒号
  • 安全例外

那么,如何在不吞咽其他异常的情况下捕获所有异常并将它们显示给用户呢?

显然,通过完美的编码,您可以消除这两个问题:

  • 参数异常
  • ArgumentNullException

如果编写一个(可能很痛苦)检查,可以消除PathToolOngException。但为什么要复制代码来检查微软写的代码呢?

但是,即使您进行了所有检查,也可能会发生其他异常:

  • 目录未找到异常
  • 异常
  • 未授权访问异常
  • 文件未找到异常
  • 冒号
  • 安全例外

文件和文件夹可以在打开文件时被删除,安全权限可以更改等。

除了向用户显示消息,我看不到您在这些场景中可以做什么。你要找到操作系统找不到的目录吗?修复权限?将代码注入操作系统以使不支持的操作得到支持?英雄联盟我只看到一条错误信息。

因此,如果每次打开一个文件来读取文本时都必须捕获所有这些异常,那么我的代码必须是长的和重复的,除非我通过捕获异常来吞咽异常。

创建一个fileException并捕获实际处理文件时可能出现的所有异常是一个好的实践吗?我想到的是:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
public class FileException : Exception
{
    public FileException( Exception e )
        : base( e.Message, e.InnerException )
    {
    }
}

public static class FileNoBS
{
    public static string ReadAllText2( string path )
    {
        try
        {
            return File.ReadAllText( path );
        }
        catch ( ArgumentNullException e )
        {
            throw new FileException( e );
        }
        catch ( ArgumentException e )
        {
            throw new FileException( e );
        }
        catch ( PathTooLongException e )
        {
            throw new FileException( e );
        }
        catch ( DirectoryNotFoundException e )
        {
            throw new FileException( e );
        }
        catch ( FileNotFoundException e )
        {
            throw new FileException( e );
        }
        catch ( IOException e )
        {
            throw new FileException( e );
        }
        catch ( UnauthorizedAccessException e )
        {
            throw new FileException( e );
        }
        catch ( NotSupportedException e )
        {
            throw new FileException( e );
        }
        catch ( SecurityException e )
        {
            throw new FileException( e );
        }
    }    
}

然后,当捕获异常时,我只需编写以下内容:

1
2
3
4
5
6
7
8
        try
        {
            string text = FileNoBS.ReadAllText2( path );
        }
        catch ( FileException e )
        {
            // display error to user
        }

我真的不明白为什么微软没有以某种方式将所有这些异常分组到一起。我是错过了什么,还是这是个好习惯?


您列出的异常有两个不同的类别——它们表示编码错误,它们表示运行时问题。第一类中的异常是可以预防的,这是绝对正确的:您可以以一种永远不会发生的方式编写代码。例如,如果您的代码null检查了路径,您就不会有在ReadAllText的调用中得到ArgumentNullException的危险。让我们逐个分析剩余的异常:

  • IOExceptionDirectoryNotFoundExceptionFileNotFoundException—如果你抓到IOException,三个都会被抓获。
  • UnauthorizedAccessException—应单独捕获。
  • 通过在调用之前验证路径,可以防止NotSupportedException
  • SecurityException—可以在调用之前通过检查权限来阻止。

最后,通过捕获IOExceptionUnauthorizedAccessException,可以覆盖指示运行时问题的所有异常,并通过预先验证计划通过的参数和检查代码的运行时环境来防止其他异常的发生。


您要查找的是System.IO.IOException。

System.IO.IOException的继承层次结构:

1
2
3
4
5
6
7
8
9
10
11
System.Object
  System.Exception
    System.SystemException
      System.IO.IOException
        System.IO.DirectoryNotFoundException
        System.IO.DriveNotFoundException
        System.IO.EndOfStreamException
        System.IO.FileLoadException
        System.IO.FileNotFoundException
        System.IO.PathTooLongException
        System.IO.PipeException

ArgumentException由两个众所周知的异常继承:

1
2
3
4
5
6
7
System.Object
  System.Exception
    System.SystemException
      System.ArgumentException
        System.ArgumentNullException
        System.ArgumentOutOfRangeException
        //...

一些典型的算术例外:

1
2
3
4
5
6
7
System.Object
  System.Exception
    System.SystemException
      System.ArithmeticException
        System.DivideByZeroException
        System.NotFiniteNumberException
        System.OverflowException

同样值得注意的是threadabortexception,它应该在桌面应用程序中使用的异步事件委托中捕获,或者在重定向/终止httpresponse时在ASP.NET中捕获。

其他异常太基本,不能有更多的"专门的基本异常"。在System.Exception的继承层次结构的引用和System.SystemException的继承层次结构中或通过反射查找它们。