c# - System.IO.Directory.Exists 在 LINQ 语句中失败,但在 fo

.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

附言

使用类似 Glob 的 globbing 库可能是个好主意(3M NuGet 下载)将所有此代码替换为:

var root = new DirectoryInfo(autodeskPath);
var templates = root.GlobFileSystemInfos("*Inventor*/Templates/**/*.*");

.NET Core 本身使用 file globbing通过Microsoft.Extensions.FileSystemGlobbing包。

Matcher matcher = new();
matcher.AddIncludePatterns(new[] { "*Inventor*/Templates/**/*.*" });

foreach (string file in matcher.GetResultsInFullPath(autodeskPath))
{
    Console.WriteLine(file);
}

关于c# - System.IO.Directory.Exists 在 LINQ 语句中失败,但在 foreach 循环中不失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/71764267/

相关文章:

authentication - 是 CQRS 中的登录/注册命令或查询

c# - 使用 EF Core 按 Id 检索实体的通用方法

python - `__ge__` 在 dict.values() 上使用时失败

java - 如何在 Java 中创建包含运算符的变量?

haskell - 在 Haskell 中日志记录功能的不同实现之间切换的有效方法?

java - 如何使用 Collectors.collectionAndThen 和 Collect

c - 在格式控制字符串中使用消息

node.js - Remix.run 不使用 node.js 作为后端吗?

python - 将列表附加到现有数据框

c++ - 临时初始化和引用初始化