[SupportedOSPlatform("iOS")]
意味着 API 在 iOS
上及其超集平台 MacCatalyst
上均受支持。 可以使用 [UnsupportedOSPlatform("MacCatalyst")]
特性排除这一隐含的支持。
[UnsupportedOSPlatform("iOS")
意味着 iOS
和 MacCatalyst
不支持 API。 可以使用 [SupportedOSPlatform("MacCatalyst")]
特性排除这一隐含的支持缺失。
考虑下面的覆盖率矩阵,其中 ✔️ 指示平台受支持,而 ❌ 指示平台不受支持。
SupportedOSPlatform(subset)
SupportedOSPlatform(superset)
UnsupportedOSPlatform(subset)
UnsupportedOSPlatform(superset)
相同的规则也适用于 SupportedOSPlatformGuard
和 UnsupportedOSPlatformGuard
特性。
下面的代码段演示如何组合特性来设置正确的支持级别。
// MacCatalyst is a superset of iOS therefore supported on iOS and MacCatalyst
[SupportedOSPlatform("iOS")]
public void ApiOnlySupportedOnIOSAndMacCatalyst() { }
// Does not imply iOS, only supported on MacCatalyst
[SupportedOSPlatform("MacCatalyst")]
public void ApiOnlySupportedOnMacCatalyst() { }
[SupportedOSPlatform("iOS")] // Supported on iOS and MacCatalyst
[UnsupportedOSPlatform("MacCatalyst")] // Removes implied MacCatalyst support
public void ApiOnlySupportedOnIos() { }
// Unsupported on iOS and MacCatalyst
[UnsupportedOSPlatform("iOS")]
public void ApiUnsupportedOnIOSAndMacCatalyst();
// Does not imply iOS, only unsupported on MacCatalyst
[UnsupportedOSPlatform("MacCatalyst")]
public void ApiUnsupportedOnMacCatalyst() { }
[UnsupportedOSPlatform("iOS")] // Unsupported on iOS and MacCatalyst
[SupportedOSPlatform("MacCatalyst")] // Removes implied MacCatalyst unsupportedness
public void ApiUnsupportedOnIos() { }
特性组合的高级方案
如果存在 [SupportedOSPlatform]
和 [UnsupportedOSPlatform]
属性的组合,则所有属性都按 OS 平台标识符分组:
仅受支持的列表。 如果每个 OS 平台的最低版本是 [SupportedOSPlatform]
属性,则 API 会被视为仅在列出的平台上受支持,但在所有其他平台上不受支持。 每个平台的可选 [UnsupportedOSPlatform]
属性只能具有较高版本的最低支持版本,这表示从指定的版本开始删除 API。
// API is only supported on Windows from version 6.2 to 10.0.19041.0 and all versions of Linux
// The API is considered not supported for all other platforms.
[SupportedOSPlatform("windows6.2")]
[UnsupportedOSPlatform("windows10.0.19041.0")]
[SupportedOSPlatform("linux")]
public void ApiSupportedFromWindows80SupportFromCertainVersion();
仅不受支持的列表。 如果每个 OS 平台的最低版本是 [UnsupportedOSPlatform]
属性,则 API 会被视为仅在列出的平台上不受支持,但在所有其他平台上受支持。 此列表可能具有包含相同平台但版本较高的 [SupportedOSPlatform]
属性,这表示从该版本开始支持 API。
// The API is unsupported on all Linux versions was unsupported on Windows until version 10.0.19041.0.
// The API is considered supported everywhere else without constraints.
[UnsupportedOSPlatform("windows")]
[SupportedOSPlatform("windows10.0.19041.0")]
[UnsupportedOSPlatform("linux")]
public void ApiSupportedFromWindows8UnsupportedFromWindows10();
不一致的列表。 如果某些平台的最低版本为 [SupportedOSPlatform]
,而其他平台的最低版本为 [UnsupportedOSPlatform]
,则会被视为不一致,不受分析器支持。 如果发生不一致,分析器将忽略 [UnsupportedOSPlatform]
平台。
如果 [SupportedOSPlatform]
和 [UnsupportedOSPlatform]
属性的最低版本相同,则分析器会将平台视为“仅受支持的列表”的一部分。
仅当遵守规则“子批注可以缩小平台支持范围,但无法将其扩大”时才会应用子级属性。
当父级具有仅受支持的列表时,子成员属性无法添加新的平台支持,因为这会扩大父级支持。 只能将新平台支持添加到父级本身。 但对于具有更高版本的同一平台,子级可以有 Supported
属性,因为这会缩小支持。 另外,子级可以有同一平台的 Unsupported
属性,因为这也会缩小父级支持。
当父级有仅限不支持的列表时,子成员属性可以添加对新平台的支持,因为这会缩小父级支持。 但它不能具有与父级所在平台相同的 Supported
属性,因为这会扩大父级支持。 只能将对同一平台的支持添加到应用了原始 Unsupported
属性的父级。
如果对具有相同 platform
名称的 API 应用 [SupportedOSPlatform("platformVersion")]
一次以上,则分析器仅考虑最低版本的 API。
如果对具有相同 platform
名称的 API 应用 [UnsupportedOSPlatform("platformVersion")]
两次以上,则分析器仅考虑最早版本的两个 API。
最初受支持但在更高版本中不受支持(删除)的 API 并不希望在更高版本中重新受支持。
属性的工作方式及其导致的诊断的示例
// An API supported only on Windows all versions.
[SupportedOSPlatform("Windows")]
public void WindowsOnlyApi() { }
// an API supported on Windows and Linux.
[SupportedOSPlatform("Windows")]
[SupportedOSPlatform("Linux")]
public void SupportedOnWindowsAndLinuxOnly() { }
// an API only supported on Windows 6.2 and later, not supported for all other.
// an API is removed/unsupported from version 10.0.19041.0.
[SupportedOSPlatform("windows6.2")]
[UnsupportedOSPlatform("windows10.0.19041.0")]
public void ApiSupportedFromWindows8UnsupportedFromWindows10() { }
// an Assembly supported on Windows, the API added from version 10.0.19041.0.
[assembly: SupportedOSPlatform("Windows")]
[SupportedOSPlatform("windows10.0.19041.0")]
public void AssemblySupportedOnWindowsApiSupportedFromWindows10() { }
public void Caller()
WindowsOnlyApi(); // warns: This call site is reachable on all platforms. 'WindowsOnlyApi()' is only supported on: 'windows'
// This call site is reachable on all platforms. 'SupportedOnWindowsAndLinuxOnly()' is only supported on: 'Windows', 'Linux'
SupportedOnWindowsAndLinuxOnly();
// This call site is reachable on all platforms. 'ApiSupportedFromWindows8UnsupportedFromWindows10()' is only supported on: 'windows' from version 6.2 to 10.0.19041.0
ApiSupportedFromWindows8UnsupportedFromWindows10();
// for same platform analyzer only warn for the latest version.
// This call site is reachable on all platforms. 'AssemblySupportedOnWindowsApiSupportedFromWindows10()' is only supported on: 'windows' 10.0.19041.0 and later
AssemblySupportedOnWindowsApiSupportedFromWindows10();
// an API not supported on android but supported on all other.
[UnsupportedOSPlatform("android")]
public void DoesNotWorkOnAndroid() { }
// an API was unsupported on Windows until version 6.2.
// The API is considered supported everywhere else without constraints.
[UnsupportedOSPlatform("windows")]
[SupportedOSPlatform("windows6.2")]
public void StartedWindowsSupportFromVersion8() { }
// an API was unsupported on Windows until version 6.2.
// Then the API is removed (unsupported) from version 10.0.19041.0.
// The API is considered supported everywhere else without constraints.
[UnsupportedOSPlatform("windows")]
[SupportedOSPlatform("windows6.2")]
[UnsupportedOSPlatform("windows10.0.19041.0")]
public void StartedWindowsSupportFrom8UnsupportedFrom10() { }
public void Caller2()
DoesNotWorkOnAndroid(); // This call site is reachable on all platforms.'DoesNotWorkOnAndroid()' is unsupported on: 'android'
// This call site is reachable on all platforms. 'StartedWindowsSupportFromVersion8()' is unsupported on: 'windows' 6.2 and before.
StartedWindowsSupportFromVersion8();
// This call site is reachable on all platforms. 'StartedWindowsSupportFrom8UnsupportedFrom10()' is supported on: 'windows' from version 6.2 to 10.0.19041.0
StartedWindowsSupportFrom8UnsupportedFrom10();
处理报告的警告
处理这些诊断的建议方法是确保在相应的平台上运行时仅调用特定于平台的 API。 下面是可用于解决警告的选项;选择最适合你的情况的选项:
保护调用。 可以通过在运行时有条件地调用代码来实现此目的。 使用平台检查方法之一检查是否正在所需的 Platform
上运行,例如 OperatingSystem.Is<Platform>()
或 OperatingSystem.Is<Platform>VersionAtLeast(int major, int minor = 0, int build = 0, int revision = 0)
。 示例。
将调用站点标记为特定于平台。 还可以选择将自己的 API 标记为特定于平台,从而有效地将要求转发给调用方。 将包含的方法或类型或具有相同属性的整个程序集标记为引用的依赖平台的调用。 示例。
通过平台检查来断言调用站点。 如果不希望在运行时增加额外的 if
语句,请使用 Debug.Assert(Boolean)。 示例。
删除代码。 通常不是你想要的,因为这意味着当 Windows 用户使用代码时将失真。 对于存在跨平台替代方法的情况,更好的做法可能是在特定于平台的 API 上使用此方法。
禁止显示警告。 通过 EditorConfig 条目或 #pragma warning disable CA1416
即可禁止显示警告。 但是,当使用特定于平台的 API 时,如非绝对必要,请勿使用此选项。
使用 #pragma
预编译器指令来禁用警告时,目标标识符区分大小写。 例如,ca1416
不会实际禁用警告 CA1416。
保护方法的平台名称应与依赖平台的调用 API 平台名称匹配。 如果调用 API 的平台字符串包括版本:
对于 [SupportedOSPlatform("platformVersion")]
属性,保护方法平台 version
应大于或等于调用平台的 Version
。
对于 [UnsupportedOSPlatform("platformVersion")]
属性,保护方法平台 version
应小于或等于调用平台的 Version
。
public void CallingSupportedOnlyApis() // Allow list calls
if (OperatingSystem.IsWindows())
WindowsOnlyApi(); // will not warn
if (OperatingSystem.IsLinux())
SupportedOnWindowsAndLinuxOnly(); // will not warn, within one of the supported context
// Can use &&, || logical operators to guard combined attributes
if (OperatingSystem.IsWindowsVersionAtLeast(6, 2) && !OperatingSystem.IsWindowsVersionAtLeast(10, 0, 19041)))
ApiSupportedFromWindows8UnsupportedFromWindows10();
if (OperatingSystem.IsWindowsVersionAtLeast(10, 0, 19041, 0))
AssemblySupportedOnWindowsApiSupportedFromWindows10(); // Only need to check latest supported version
public void CallingUnsupportedApis()
if (!OperatingSystem.IsAndroid())
DoesNotWorkOnAndroid(); // will not warn
if (!OperatingSystem.IsWindows() || OperatingSystem.IsWindowsVersionAtLeast(6, 2))
StartedWindowsSupportFromVersion8(); // will not warn
if (!OperatingSystem.IsWindows() || // supported all other platforms
(OperatingSystem.IsWindowsVersionAtLeast(6, 2) && !OperatingSystem.IsWindowsVersionAtLeast(10, 0, 19041)))
StartedWindowsSupportFrom8UnsupportedFrom10(); // will not warn
如果需要保护面向新 OperatingSystem API 不可用的 netstandard
或 netcoreapp
的代码,则可以使用 RuntimeInformation.IsOSPlatform API 并由分析器遵守。 但不如 OperatingSystem 中添加的新 API 那样优化。 如果平台在 OSPlatform 结构中不受支持,则可以调用 OSPlatform.Create(String) 并传入平台名称(分析器也会遵循此名称)。
public void CallingSupportedOnlyApis()
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
SupportedOnWindowsAndLinuxOnly(); // will not warn
if (RuntimeInformation.IsOSPlatform(OSPlatform.Create("browser")))
ApiOnlySupportedOnBrowser(); // call of browser specific API
如前所示,分析器能识别 OperatingSystem 类型中的平台保护静态方法,例如 OperatingSystem.IsWindows
,还有 RuntimeInformation.IsOSPlatform。 但是,你可能想要将保护结果缓存在字段中,并重复使用它,或者使用自定义保护方法来检查平台。 分析器需要将此类 API 识别为自定义保护,且不能针对它们保护的 API 发出警告。 .NET 6 中引入了保护属性以支持此方案:
SupportedOSPlatformGuardAttribute
会批注可充当用 SupportedOSPlatformAttribute 批注的 API 的保护的 API。
UnsupportedOSPlatformGuardAttribute
会批注可充当用 UnsupportedOSPlatformAttribute 批注的 API 的保护的 API。
这些特性可选择性地包含版本号。 可以多次应用这些特性来保护多个平台,并可用于批注字段、属性或方法。
class Test
[UnsupportedOSPlatformGuard("browser")] // The platform guard attribute
#if TARGET_BROWSER
internal bool IsSupported => false;
#else
internal bool IsSupported => true;
#endif
[UnsupportedOSPlatform("browser")]
void ApiNotSupportedOnBrowser() { }
void M1()
ApiNotSupportedOnBrowser(); // Warns: This call site is reachable on all platforms.'ApiNotSupportedOnBrowser()' is unsupported on: 'browser'
if (IsSupported)
ApiNotSupportedOnBrowser(); // Not warn
[SupportedOSPlatform("Windows")]
[SupportedOSPlatform("Linux")]
void ApiOnlyWorkOnWindowsLinux() { }
[SupportedOSPlatformGuard("Linux")]
[SupportedOSPlatformGuard("Windows")]
private readonly bool _isWindowOrLinux = OperatingSystem.IsLinux() || OperatingSystem.IsWindows();
void M2()
ApiOnlyWorkOnWindowsLinux(); // This call site is reachable on all platforms.'ApiOnlyWorkOnWindowsLinux()' is only supported on: 'Linux', 'Windows'.
if (_isWindowOrLinux)
ApiOnlyWorkOnWindowsLinux(); // Not warn
平台名称应与依赖平台的调用 API 匹配。 如果平台字符串包括版本:
对于 [SupportedOSPlatform("platformVersion")]
属性,调用站点平台 version
应大于或等于调用平台的 Version
对于 [UnsupportedOSPlatform("platformVersion")]
属性,调用站点平台 version
应小于或等于调用平台的 Version
// an API supported only on Windows.
[SupportedOSPlatform("windows")]
public void WindowsOnlyApi() { }
// an API supported on Windows and Linux.
[SupportedOSPlatform("Windows")]
[SupportedOSPlatform("Linux")]
public void SupportedOnWindowsAndLinuxOnly() { }
// an API only supported on Windows 6.2 and later, not supported for all other.
// an API is removed/unsupported from version 10.0.19041.0.
[SupportedOSPlatform("windows6.2")]
[UnsupportedOSPlatform("windows10.0.19041.0")]
public void ApiSupportedFromWindows8UnsupportedFromWindows10() { }
// an Assembly supported on Windows, the API added from version 10.0.19041.0.
[assembly: SupportedOSPlatform("Windows")]
[SupportedOSPlatform("windows10.0.19041.0")]
public void AssemblySupportedOnWindowsApiSupportedFromWindows10() { }
[SupportedOSPlatform("windows6.2")] // call site attributed Windows 6.2 or above.
public void Caller()
WindowsOnlyApi(); // will not warn as call site is for Windows.
// will not warn as call site is for Windows all versions.
SupportedOnWindowsAndLinuxOnly();
// will not warn for the [SupportedOSPlatform("windows6.2")] attribute, but warns for [UnsupportedOSPlatform("windows10.0.19041.0")]
// This call site is reachable on: 'windows' 6.2 and later. 'ApiSupportedFromWindows8UnsupportedFromWindows10()' is unsupported on: 'windows' 10.0.19041.0 and later.
ApiSupportedFromWindows8UnsupportedFromWindows10();
// The call site version is lower than the calling version, so warns:
// This call site is reachable on: 'windows' 6.2 and later. 'AssemblySupportedOnWindowsApiSupportedFromWindows10()' is only supported on: 'windows' 10.0.19041.0 and later
AssemblySupportedOnWindowsApiSupportedFromWindows10();
[SupportedOSPlatform("windows10.0.22000")] // call site attributed with windows 10.0.22000 or above.
public void Caller2()
// This call site is reachable on: 'windows' 10.0.22000 and later. 'ApiSupportedFromWindows8UnsupportedFromWindows10()' is unsupported on: 'windows' 10.0.19041.0 and later.
ApiSupportedFromWindows8UnsupportedFromWindows10();
// will not warn as call site version higher than calling API.
AssemblySupportedOnWindowsApiSupportedFromWindows10();
[SupportedOSPlatform("windows6.2")]
[UnsupportedOSPlatform("windows10.0.19041.0")] // call site supports Windows from version 6.2 to 10.0.19041.0.
public void Caller3()
// will not warn as caller has exact same attributes.
ApiSupportedFromWindows8UnsupportedFromWindows10();
// The call site reachable for the version not supported in the calling API, therefore warns:
// This call site is reachable on: 'windows' from version 6.2 to 10.0.19041.0. 'AssemblySupportedOnWindowsApiSupportedFromWindows10()' is only supported on: 'windows' 10.0.19041.0 and later.
AssemblySupportedOnWindowsApiSupportedFromWindows10();
// an API not supported on Android but supported on all other.
[UnsupportedOSPlatform("android")]
public void DoesNotWorkOnAndroid() { }
// an API was unsupported on Windows until version 6.2.
// The API is considered supported everywhere else without constraints.
[UnsupportedOSPlatform("windows")]
[SupportedOSPlatform("windows6.2")]
public void StartedWindowsSupportFromVersion8() { }
// an API was unsupported on Windows until version 6.2.
// Then the API is removed (unsupported) from version 10.0.19041.0.
// The API is considered supported everywhere else without constraints.
[UnsupportedOSPlatform("windows")]
[SupportedOSPlatform("windows6.2")]
[UnsupportedOSPlatform("windows10.0.19041.0")]
public void StartedWindowsSupportFrom8UnsupportedFrom10() { }
[UnsupportedOSPlatform("windows")] // Caller no support Windows for any version.
public void Caller4()
// This call site is reachable on all platforms.'DoesNotWorkOnAndroid()' is unsupported on: 'android'
DoesNotWorkOnAndroid();
// will not warns as the call site not support Windows at all, but supports all other.
StartedWindowsSupportFromVersion8();
// same, will not warns as the call site not support Windows at all, but supports all other.
StartedWindowsSupportFrom8UnsupportedFrom10();
[UnsupportedOSPlatform("windows")]
[UnsupportedOSPlatform("android")] // Caller not support Windows and Android for any version.
public void Caller4()
DoesNotWorkOnAndroid(); // will not warn as call site not supports Android.
// will not warns as the call site not support Windows at all, but supports all other.
StartedWindowsSupportFromVersion8();
// same, will not warns as the call site not support Windows at all, but supports all other.
StartedWindowsSupportFrom8UnsupportedFrom10();
平台保护示例中使用的所有条件检查也可以用作 Debug.Assert(Boolean) 的条件。
// An API supported only on Linux.
[SupportedOSPlatform("linux")]
public void LinuxOnlyApi() { }
public void Caller()
Debug.Assert(OperatingSystem.IsLinux());
LinuxOnlyApi(); // will not warn
.NET 5 中的目标框架名称
批注特定于平台的 API 并检测其用法
在特定平台上将 API 批注为不受支持
CA1416 平台兼容性分析器