C# 如何在C语言中产生并捕获必要的异常?

C# 如何在C语言中产生并捕获必要的异常?,c#,.net,try-catch,yield,C#,.net,Try Catch,Yield,我正在研究以下方法: private IEnumerable<TreeNode> GetChildNodes(TreeNode parent) { string path = parent.Tag.ToString(); // Add Directories string[] subdirs = Directory.GetDirectories(path); foreach (string subdi

我正在研究以下方法:

    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都可以抛出我想要捕获的异常之外,这一切都很好


我无法捕获使用这些方法的代码片段,因为我使用的是收益率。如果存在捕获,则无法将收益率放在try的主体中。我知道我可以删除收益率,只需将我的孩子添加到一个集合中,但我很好奇,如何有人会从这两种方法中捕获IOException,并仍然使用收益率?

第一部分如何:

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

第二个也是如此。你不需要在试块内屈服。如果这没有帮助,请编写任何您希望有效的代码,这样我们就可以看到在抛出异常时您打算做什么。

第一部分如何:

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

第二个也是如此。你不需要在试块内屈服。如果这没有帮助,请编写任何您希望有效的代码,这样我们就可以看到在抛出异常时您打算做什么。

异常将通过调用GetDirectory和GetFiles抛出,因此您可以尝试捕获它们,而不是针对每个,

调用GetDirectory和GetFile将引发异常,因此您可以尝试捕获它们,而不是for each,

在调用它们的代码中,您不能捕获外部异常吗?

您不能捕获外部异常吗,在调用它们的代码中?

可以创建添加特殊错误处理策略的帮助器方法:

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

   return subdirectories;
}

很明显,用相关的电话代替。当然,我假设您甚至想要在错误上让步,但我谦虚地接受这种假设可能是错误的:

您可以创建添加特殊错误处理策略的帮助器方法:

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

   return subdirectories;
}

很明显,用相关的电话代替。当然,我假设您希望即使在出现错误时也能让步,但我谦虚地承认这一假设可能是错误的:

我要提醒您不要使用异常作为控制流的方法-如果您不确定目录或路径将返回有效的结果,首先检查它——几乎所有这些异常都可以通过参数检查来防止,通常如下所示

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;
    }
}

这里有足够的优化空间和进一步分解的时机,通常的评论适用于竞争条件,并且缺乏在另一个线程上删除目录之前检查目录是否存在的保证,因此现在您可以通过在Get{Directories,Files}周围包装try/catch使其更加健壮像Jon或xanatos建议的EDIT:这样的调用,我现在已经在这里作为SafeIO结束了,但是现在您只能捕获易受此IOException或DirectoryNotFoundException影响的特定异常,并将其保留为真正的异常情况。

如果您不确定,我建议不要使用异常作为控制流的方法如果目录或路径将返回一个有效的结果,请首先检查它-几乎所有这些异常都可以通过参数检查来防止,通常如下所示

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;
    }
}

这里有足够的优化空间和进一步分解的时机,通常的评论适用于竞争条件,并且缺乏在另一个线程上删除目录之前检查目录是否存在的保证,因此现在您可以通过在Get{Directories,Files}周围包装try/catch使其更加健壮像Jon或xanatos建议的EDIT:这样的调用,我现在已经作为SafeIO结束了,但是现在您只能捕获易受此IOException或DirectoryNotFoundException影响的特定异常,并将其保留为真正的异常情况。

。正如答案中所说的那样,这不仅仅是竞赛条件会抛出异常,而是无声的失败,结果是空的。如果目录不存在于您期望的位置,您应该尽早失败并快速失败。例外情况是一个完全合理的方法。正如答案中所说的那样,这不仅仅是竞赛条件会抛出异常,而是无声的失败,结果是空的。如果目录不存在于您期望的位置,您应该尽早失败并快速失败。例外情况是完全合理的做法。