2011-02-15 27 views
1

我有以下方法我的工作:我该如何获得并在C#中捕获必要的例外?

private IEnumerable<TreeNode> GetChildNodes(TreeNode parent) 
    { 
     string path = parent.Tag.ToString(); 

     // Add Directories 
     string[] subdirs = Directory.GetDirectories(path); 

     foreach (string subdir in subdirs) 
     { 
      yield return GetChildNode(subdir); 
     } 

     // Add Files 
     string[] files = Directory.GetFiles(path); 

     foreach (string file in files) 
     { 
      var child = GetChildNode(file); 
      fileNodeMap[file] = child; 
      yield return child; 
     } 
    } 

这正常工作与Directory.GetDirectories()和Directory.GetFiles(除外)都可以扔,我想捕获异常。

我不能赶上其利用这些方法的代码片段,由于我使用的产率(产率不能置于一试的主体内,如果有一个陷阱)。我知道我可以删除产量,并简单地添加到我的孩子收集,但我很好奇,有人会从这两种方法捕捉IOExceptions,并仍然利用收益率?

回答

5

如何像(为第一部分):

string[] subdirs; 
try 
{ 
    subdirs = Directory.GetDirectories(path); 
} 
catch (IOException e) 
{ 
    // Do whatever you need here 
    subdirs = new string[0]; 
} 

同样地,对于第二。您不需要在该尝试块内输出。如果这没有帮助,请写任何代码是有效的,以便我们可以看到你打算做什么,如果抛出异常。

0

异常将通过GetDirectoriesGetFiles通话被抛出,这样你就可以try-catch他们,而不是在for-each的,

0

你能不能捕捉异常,在调用它们的代码?

0

你可以让helper方法添加特殊的错误处理酱:

private string[] GetSubdirectoriesWithSpecialSauce(string path) 
{ 
    string[] subdirectories; 
    try 
    { 
     subdirectories = Directory.GetDirectories(path); 
    } 
    catch (IOException ioe) 
    { 
     ShutdownWOPR(); 
     CallDrFalken(); 
    } 

    return subdirectories; 
} 

而且很明显替代的相关电话。我当然假设你想,以至产生的错误,但我虚心接受,这一假设可能是错的:)

0

我奉劝不要使用异常的控制流的方法 - 如果你不知道该目录或路径将返回一个有效的结果,首先检查它 - 几乎所有这些异常可以通过参数检查来阻止,一般如下所示。

private IEnumerable<TreeNode> GetChildNodes(TreeNode parent) 
{ 
    string path = parent.Tag.ToString(); 

    if (String.IsNullOrEmpty (path) || String.IsNullOrWhiteSpace (path)) 
     yield break; 

    // I'm not aware of a constant/enum for the maximum allowed path length here :(
    if (path.Length > 260 || path.Any (Path.GetInvalidPathChars().Contains)) 
     yield break; 

    if (!Directory.Exists (path)) 
     yield break; 

    Func<string[], Func<string[],string>,> SafeIO = (fn, arg) => { 
     try { 
      return fn (p); 
     } catch (IOException) { 
      return new string[0]; 
     } 
    }; 

    // Add Directories 
    string[] subdirs = SafeIO (Directory.GetDirectories, path); 
    foreach (string subdir in subdirs) 
     yield return GetChildNode(subdir); 

    // Add Files 
    string[] files = SafeIO (Directory.GetFiles, path); 
    foreach (string file in files) { 
     var child = GetChildNode(file); 
     fileNodeMap[file] = child; 
     yield return child; 
    } 
} 

足够的空间优化有(和成熟,进一步分解),和通常的解释适用有关种族的条件和缺乏检查,如果它是另一个线程上删除之前存在的目录的保证,所以现在你可以通过缠绕在获取一个try/catch使这更健壮{目录,文件}调用像乔恩或萨那托斯建议(编辑:那现在我已经结束了这里SafeIO) - 但现在你可以只抓取(IOExceptionDirectoryNotFoundException)的特定例外情况,并将其保留用于真正的例外情况。

+1

Yuck。这不仅仅是因为竞争条件的原因,它会抛出异常(正如答案中所提到的那样),这是无结果的失败。如果目录不存在于您期望的目录中,则您应该尽早失败并快速失败。例外是完全合理的方式。 – 2014-04-15 10:32:38