【问题标题】:Try-Catch block with two catch clauses with similar code带有两个具有相似代码的 catch 子句的 Try-Catch 块
【发布时间】:2019-09-09 08:00:17
【问题描述】:

我正在使用带有两个 catch 子句的 try-catch 块。我想从特定路径加载 XML 文件,并检查目录是否存在于第一个子句中以创建目录,并在第二个子句中检查文件是否存在以创建文件。但是,我知道如果目录不存在,文件也不存在。

所以我在想是否有办法不复制代码。我知道我可以创建一个布尔变量,然后检查它是否为真并创建文件,但我认为可能有一个不错的、干净的解决方案,我只是不知道如何搜索。

XmlDocument document = new XmlDocument();

try
{
    document.Load(folderPath + @"\XMLfile.xml"); // folderPath variable is assigned before depending on user input
}
catch(System.IO.DirectoryNotFoundException)
{
    // if folder doesn't exist then the file will not either
    System.IO.Directory.CreateDirectory(folderPath);
    document.LoadXml("<?xml version=\"1.0\"?> \n" +
                     "<elements> \n" +
                     "</elements>");
}
catch (System.IO.FileNotFoundException)
{
    // if folder exists then the file might as well, if not, creating the file's structure
    document.LoadXml("<?xml version=\"1.0\"?> \n" +
                     "<elements> \n" +
                     "</elements>");
}

理想情况下,我想知道是否有办法避免重复代码但仍保留两个异常。两个 catch 子句中的布尔变量(例如 createFile)是否是以某种不错的方式进行的唯一方法?

【问题讨论】:

  • 写一个单独的方法来调用?如果你愿意,它可以是一个本地函数。

标签: c# .net file try-catch


【解决方案1】:

怎么样

XmlDocument document = new XmlDocument();

try
{
   document.Load(folderPath + @"\XMLfile.xml");
}
catch (Exception e) when (e is DirectoryNotFoundException || e is FileNotFoundException)
{
    Directory.CreateDirectory(folderPath);
    document.LoadXml("<?xml version=\"1.0\"?> \n" +
                     "<elements> \n" +
                     "</elements>");
}

Directory.CreateDirectory(folderPath); 如果目录已经存在,则不执行任何操作。所以,在那里调用它是安全的。

【讨论】:

    【解决方案2】:

    如果您使用的是 C# 6 或更高版本,您可以使用when 关键字过滤指定条件的异常:

    XmlDocument document = new XmlDocument();
    
    try
    {
        document.Load(folderPath + @"\XMLfile.xml"); // folderPath variable is assigned before depending on user input
    }
    catch (Exception ex) when (ex is System.IO.DirectoryNotFoundException || ex is System.IO.FileNotFoundException)
    {
        // if folder doesn't exist then the file will not either
        System.IO.Directory.CreateDirectory(folderPath);
        document.LoadXml("<?xml version=\"1.0\"?> \n" +
                         "<elements> \n" +
                         "</elements>");
    }
    

    但是,您没有完全相同的 catch 块,因此您甚至可以考虑将所有内容保持原样。否则,您需要在 catch 块内引入另一个检查以调用 CreateDirectory

    【讨论】:

    • 我不久前发布了同样的内容:p
    • @swdon haha​​h 几乎在同一时间:D
    【解决方案3】:

    检查this thread。您将拥有基本的文件夹选择器,并且您不必用 try catch 块来挠头。主要取决于您的应用程序。如果是服务器端的,您应该阅读有关 Streams(FileStream、StreamReader 等)的内容here

    【讨论】:

      【解决方案4】:

      您正在使用异常来处理正常的控制流。您捕获的错误应该毫无例外地处理。

      尽管如此,由于竞态条件,您仍然可以获得异常,因此您仍然需要异常处理。

      您还应该考虑为格式错误的 xml 添加额外的处理。

      public static XmlDocument LoadOrCreateXmlDocument(string folderPath)
      {
          if (!Directory.Exists(folderPath))
          {
              Directory.CreateDirectory(folderPath);
          }
      
          string fileName = Path.Combine(folderPath + @"\XMLfile.xml");
      
          if (TryLoadXmlDocument(fileName, out var document))
          {
              return document;
          }
      
          XmlDocument newDocument = new XmlDocument();
          newDocument.LoadXml("<?xml version=\"1.0\"?> \n" +
                              "<elements> \n" +
                              "</elements>");
      
          return newDocument;
      }
      
      public static bool TryLoadXmlDocument(string fileName, out XmlDocument document)
      {
          document = new XmlDocument();
      
          if (File.Exists(fileName))
          {
              try
              {
                  document.Load(fileName);
                  return true;
              }
              catch (FileNotFoundException)
              {
                  return false;
              }
          }
      
          return false;
      }
      

      【讨论】:

        【解决方案5】:

        尽量避免从 catch 中执行太多代码。这是解决更大问题的秘诀。 更好的是使用不同的异常来确定下一步要做什么,并在方法结束时返回这个结果。

        因此,仅使用 catch 来处理异常并在以后继续执行进一步操作,而不是从 catch 内部进行。

        例如:

        bool documentLoaded = LoadXML(); // Your code in this method
        if (!documentLoaded)
          CreateXML();
        

        【讨论】:

        • 所以你宁愿推荐使用像我举的例子那样的布尔值?
        • 是的,我尝试添加一个简单的示例。返回一个值,告诉您下一步应该做什么。操作是否成功。
        【解决方案6】:

        也许最好使用方法System.IO.Directory.Exists()System.IO.Directory.Exists() 而不是捕获异常。这样你的代码会更清晰。

        XmlDocument document = new XmlDocument();
        
        if (!System.IO.Directory.Exists(folderPath))
            System.IO.Directory.CreateDirectory(folderPath);
        
        var filename = folderPath + @"\XMLfile.xml";
        
        if (System.IO.File.Exists(filename);
            document.Load(filename);
        else
            document.LoadXml("<?xml version=\"1.0\"?> \n" +
                             "<elements> \n" +
                             "</elements>");
        }
        

        【讨论】:

          猜你喜欢
          • 2016-02-14
          • 1970-01-01
          • 2011-06-01
          • 2013-11-22
          • 2014-03-10
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2018-03-04
          相关资源
          最近更新 更多