我正在使用以下方法:
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()都可以抛出我想要捕获的异常之外,这样可以正常工作。
由于我使用了yield,我无法捕获利用这些方法的代码片段(如果有一个catch,则不能将yield放在try的主体内)。我知道我可以删除产量并简单地将我的孩子添加到一个集合中,但我很好奇有人会从这两种方法中捕获IOExceptions并仍然使用yield?
答案 0 :(得分:5)
如何(第一部分):
string[] subdirs;
try
{
subdirs = Directory.GetDirectories(path);
}
catch (IOException e)
{
// Do whatever you need here
subdirs = new string[0];
}
同样的第二个。您不需要在该try块内屈服。如果这没有帮助,请写下您希望有效的任何代码,以便我们可以看到如果抛出异常,您打算做什么。
答案 1 :(得分:0)
该异常将通过GetDirectories
和GetFiles
的调用抛出,因此您可try-catch
而不是for-each
,
答案 2 :(得分:0)
你能不能在调用它们的代码中捕获在之外的异常?
答案 3 :(得分:0)
你可以制作辅助方法,添加你的特殊错误处理酱:
private string[] GetSubdirectoriesWithSpecialSauce(string path)
{
string[] subdirectories;
try
{
subdirectories = Directory.GetDirectories(path);
}
catch (IOException ioe)
{
ShutdownWOPR();
CallDrFalken();
}
return subdirectories;
}
显然可以替换相关的电话。我当然认为你甚至想要在错误上屈服,但我谦卑地接受这种假设可能是错误的:)
答案 4 :(得分: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;
}
}
有足够的优化空间(并且已经成熟进行进一步分解),通常的注释适用于竞争条件,并且缺少保证在另一个线程上删除目录之前是否存在目录,所以现在你可以制作通过在Jon或xanatos建议的Get {Directories,Files}调用周围包装一个try / catch来更强大(编辑:我现在已经将其作为SafeIO
包裹起来) - 但现在你只能抓住易受此影响的特定异常(IOException
或DirectoryNotFoundException
)并将其保留用于真正例外情况。