System.IO.Directory.Exists 在 LINQ 语句中失败,但在 foreach 循环中不失败
System.IO.Directory.Exists fails inside LINQ statement, but not in a foreach loop
.Net Framework 4.7.2
这是一个非常令人惊讶的问题...
我有这个例程从本地磁盘获取所有可用的 Inventor 模板,无论它是哪个版本:
private static IEnumerable<string> GetInventorTemplates_FAILS()
{
var publicPath = Environment.GetEnvironmentVariable("PUBLIC");
var autodeskPath = Path.Combine(publicPath, "Documents", "Autodesk");
var inventorPaths = Directory.GetDirectories(autodeskPath, "*Inventor*");
var templatePaths = inventorPaths.Select(path => Path.Combine(path, "Templates"));
var templates = templatePaths.Where(Directory.Exists).SelectMany(path => Directory.GetFiles(path, "*.*", SearchOption.AllDirectories));
// throws error ^^^^^^^^^^^^^^^^
return templates;
}
如果我运行这个代码,我得到这个错误:
System.Linq.SystemCore_EnumerableDebugView`1[System.String].get_Items() calls into native method Microsoft.Win32.Win32Native.GetFullPathName(char*, int, char*, System.IntPtr). Evaluation of native methods in this context is not supported.
更疯狂的是,如果我重写代码,手动调用 Directory.Exists
就可以了!!!
private static IEnumerable<string> GetInventorTemplates_WORKS()
{
var publicPath = Environment.GetEnvironmentVariable("PUBLIC");
var autodeskPath = Path.Combine(publicPath, "Documents", "Autodesk");
var inventorPaths = Directory.GetDirectories(autodeskPath, "*Inventor*");
var templatePaths = inventorPaths.Select(path => Path.Combine(path, "Templates"));
foreach (var path in templatePaths)
if (Directory.Exists(path)) // <- no exception!!!
foreach (var template in Directory.GetFiles(path, "*.*", SearchOption.AllDirectories))
yield return template;
}
如果您通过 QuickWatch:
检查,您会得到相同的结果
现在我可以使用重写的版本,但我很好奇我是不是幸运儿...:-)
这不是 .NET 问题。该代码 运行 没问题,您无需更改任何内容。 调试器 表示它无法在手表 window 中安全地执行查询,因此它无法显示任何结果。错误说明
Evaluation of native methods in this context is not supported.
template
不是文档列表,它是尚未执行的查询。调试器必须执行该查询才能检索结果。
这既不是问题也不罕见。在多种情况下,调试器无法安全地执行 LINQ 查询或枚举 IEnumerable 并显示结果。如果要检查结果,请显式执行查询,例如 ToList
.
PS
使用像 Glob(3M NuGet 下载)这样的 globbing 库来替换所有这些代码可能是个好主意:
var root = new DirectoryInfo(autodeskPath);
var templates = root.GlobFileSystemInfos("*Inventor*/Templates/**/*.*");
.NET Core本身使用了file globbing through the Microsoft.Extensions.FileSystemGlobbing包。
Matcher matcher = new();
matcher.AddIncludePatterns(new[] { "*Inventor*/Templates/**/*.*" });
foreach (string file in matcher.GetResultsInFullPath(autodeskPath))
{
Console.WriteLine(file);
}
.Net Framework 4.7.2
这是一个非常令人惊讶的问题...
我有这个例程从本地磁盘获取所有可用的 Inventor 模板,无论它是哪个版本:
private static IEnumerable<string> GetInventorTemplates_FAILS()
{
var publicPath = Environment.GetEnvironmentVariable("PUBLIC");
var autodeskPath = Path.Combine(publicPath, "Documents", "Autodesk");
var inventorPaths = Directory.GetDirectories(autodeskPath, "*Inventor*");
var templatePaths = inventorPaths.Select(path => Path.Combine(path, "Templates"));
var templates = templatePaths.Where(Directory.Exists).SelectMany(path => Directory.GetFiles(path, "*.*", SearchOption.AllDirectories));
// throws error ^^^^^^^^^^^^^^^^
return templates;
}
如果我运行这个代码,我得到这个错误:
System.Linq.SystemCore_EnumerableDebugView`1[System.String].get_Items() calls into native method Microsoft.Win32.Win32Native.GetFullPathName(char*, int, char*, System.IntPtr). Evaluation of native methods in this context is not supported.
更疯狂的是,如果我重写代码,手动调用 Directory.Exists
就可以了!!!
private static IEnumerable<string> GetInventorTemplates_WORKS()
{
var publicPath = Environment.GetEnvironmentVariable("PUBLIC");
var autodeskPath = Path.Combine(publicPath, "Documents", "Autodesk");
var inventorPaths = Directory.GetDirectories(autodeskPath, "*Inventor*");
var templatePaths = inventorPaths.Select(path => Path.Combine(path, "Templates"));
foreach (var path in templatePaths)
if (Directory.Exists(path)) // <- no exception!!!
foreach (var template in Directory.GetFiles(path, "*.*", SearchOption.AllDirectories))
yield return template;
}
如果您通过 QuickWatch:
检查,您会得到相同的结果现在我可以使用重写的版本,但我很好奇我是不是幸运儿...:-)
这不是 .NET 问题。该代码 运行 没问题,您无需更改任何内容。 调试器 表示它无法在手表 window 中安全地执行查询,因此它无法显示任何结果。错误说明
Evaluation of native methods in this context is not supported.
template
不是文档列表,它是尚未执行的查询。调试器必须执行该查询才能检索结果。
这既不是问题也不罕见。在多种情况下,调试器无法安全地执行 LINQ 查询或枚举 IEnumerable 并显示结果。如果要检查结果,请显式执行查询,例如 ToList
.
PS
使用像 Glob(3M NuGet 下载)这样的 globbing 库来替换所有这些代码可能是个好主意:
var root = new DirectoryInfo(autodeskPath);
var templates = root.GlobFileSystemInfos("*Inventor*/Templates/**/*.*");
.NET Core本身使用了file globbing through the Microsoft.Extensions.FileSystemGlobbing包。
Matcher matcher = new();
matcher.AddIncludePatterns(new[] { "*Inventor*/Templates/**/*.*" });
foreach (string file in matcher.GetResultsInFullPath(autodeskPath))
{
Console.WriteLine(file);
}