【问题标题】:Does .NET Standard normalize HResult values across every platform it supports?.NET Standard 是否在它支持的每个平台上标准化 HResult 值?
【发布时间】:2017-09-23 14:10:48
【问题描述】:

我正在创建一个创建随机文件的简单函数。为了线程安全,它会在重试循环中创建文件,如果文件存在,它会再次尝试。

while (true)
{
    fileName = NewTempFileName(prefix, suffix, directory);

    if (File.Exists(fileName))
    {
        continue;
    }

    try
    {
        // Create the file, and close it immediately
        using (var stream = new FileStream(fileName, FileMode.CreateNew, FileAccess.Write, FileShare.Read))
        {
            break;
        }
    }
    catch (IOException e)
    {
        // If the error was because the file exists, try again
        if ((e.HResult & 0xFFFF) == 0x00000050)
        {
            continue;
        }

        // else rethrow it
        throw;
    }
}

根据 MSDN,HResult 值来自 COM,这似乎表明它只能在 Windows 上工作,它是specifically lists them as "Win32 codes"。但这是在一个针对 .NET Standard 的库中,理想情况下它应该适用于 every platform .NET Standard supports

我想知道的是我是否可以依靠上述使用 HResult 的值来跨平台的方法? documentation 在这一点上不清楚。

如果不是,我如何确定在其他平台上期望的 HResult 值?

注意: 有一个类似的问题Does .NET define common HRESULT values?,但在 .NET 标准(以及对 .NET 的跨平台支持)存在之前就有人问过了,所以我不能依赖这个答案目的。

目前,我们的代码库仅使用:

  1. 0x00000020 - ERROR_SHARING_VIOLATION
  2. 0x00000021 - ERROR_LOCK_VIOLATION
  3. 0x00000050 - ERROR_FILE_EXISTS

我们的目标是 .NET Standard 1.5。

注意:虽然接受的答案确实满足我在这里提出的问题,但我有一个后续问题How do I make catching generic IOExceptions reliably portable across platforms?

【问题讨论】:

  • 我想您必须更具体地了解您想要依赖的场景或特定错误代码。有很多地方使用了预定义代码列表(您可以搜索hresults.cs in CoreCLR 和 fullfx 参考源代码),在某些情况下还有标准化函数like this one for file errors
  • 谢谢马丁。我添加了我目前感兴趣的 3 个错误。不过,我有点希望得到更一般的答案。通常,我们只对文件 IO 错误感兴趣。
  • 您可能希望链接到 this documentation 而不是 msdn 链接,因为它是官方 .net 标准 1.5 API 文档。 (可以肯定是MSDN的复制粘贴,不过点对点就好)
  • 我更新了链接。我还问了一个后续问题stackoverflow.com/questions/46382637
  • @MartinUllrich - 您能否具体回答ERROR_SHARING_VIOLATIONERROR_LOCK_VIOLATION 是否是跨平台的?我尝试分析您链接的代码,但似乎找不到定义这些常量的实际位置。我们有一个效率较低的后备实现,但我不希望使用它,或者至少将其限制在不太流行的平台上。

标签: c# .net .net-standard hresult


【解决方案1】:

Exception.HResult 值没有跨平台标准化。

对于 I/O 错误,.NET Core 将返回平台特定的错误代码作为 HResult。在您的示例中已经存在的文件的 HResult 属性的值在 Linux 上将是 17,对于其他 Unix 系统它可能是不同的值。

在 Unix 上将 IO 错误映射到异常的相关代码在这里:https://github.com/dotnet/corefx/blob/master/src/Common/src/Interop/Unix/Interop.IOErrors.cs

【讨论】:

  • 谢谢。不幸的是,您提供的链接仅显示代码,而不显示提供值的资源文件。该目录中似乎没有其他平台的相应文件。我是否要摆脱这一点,即上述方法不能可靠?还是有什么方法可以获得所有平台所需的所有值?请注意,对于 .NET Standard 1.5 支持的每个平台,我只需要问题中的 3 个错误。
  • 这种方法不能可靠地移植。在这种情况下,HResult 是底层操作系统返回的内容。它在 Linux、macOS、FreeBSD、... 之间可能有所不同。我将编辑帖子以使其清楚。
猜你喜欢
  • 2019-02-06
  • 1970-01-01
  • 1970-01-01
  • 2016-06-04
  • 1970-01-01
  • 1970-01-01
  • 2017-03-19
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多