In .NET 5.0 we have added new attributes to annotate platform-specific APIs. This works as follows:
[SupportedOSPlatform("...")] is considered only portable to the specified OS platforms (the attribute can be applied multiple times).[UnsupportedOSPlatform("...")] is considered unsupported only to the specified OS platforms (the attribute can be applied multiple times).We have applied [SupportedOSPlatform("windows")] attribute for some windows specific APIs. We also applied [UnsupportedOSPlatform("windows")] to the System.Security.Cryptography.OpenSsl assembly. We are applying [UnsupportedOSPlatform("browser")] for APIs that are not supported in Blazor WebAssembly (still in progress).
We have a Roslyn analyzer that informs you when you're using platform-specific APIs from a call site where the API might not be available. Because the analyzer is turned on by default, you might see additional diagnostics in your build, in case your code references any platform-specific API.
This analyzer is included in .NET 5 RC1 SDK and turned on by default.
Referencing platform-specific APIs without a proper platform context would not use any diagnostics.
Referencing platform-specific APIs without a proper platform context will produce diagnostics. Examples are below.
Using platform-dependent APIs on a component makes the code no longer work across all platforms.
[SupportedOSPlatform("windows")]) from platform-neutral or non-windows context will produce a diagnostic. public void PlayCMajor()
{
// CA1416: 'Console.Beep(int, int)' is supported on 'windows'
Console.Beep(261, 1000);
}
Note: A diagnostic is only raised if the project is targeting net5.0 and has an AnalysisLevel of 5 (the default for net5.0 projects). This also applies to multi-targeted projects. No diagnostic is raised if the project is targeting windows only (net5.0-windows), or if you are targeting netstandard or netcoreapp. Therefore, existing projects will not encounter these diagnostics until they are updated to target net5.0.
[UnsupportedOSPlatform("browser")]) when building a Blazor WebAssembly will produce diagnostics. public void CreateImage()
{
// CA1416: 'Image.FromFile(string)' is unsupported on 'browser'
Image newImage = Image.FromFile("SampImag.jpg");
}
Note: This only raises a diagnostic if the project is use the Blazor WebAssembly SDK (or has manually included browser in the MSBuild <SupportedPlatform> item group. If you're building a regular class library (targeting .NET Standard or .NET 5) you won't get any diagnostics for APIs that are unsupported by browser unless you explicitly opt-in by adding this to your project:
<ItemGroup>
<SupportedPlatform Include="browser" />
</ItemGroup>
The recommend way to deal with these diagnostics is by making sure you only call these APIs when running on the appropriate platforms. You can either achieve this by excluding the code at build time using #if and multi-targeting or by conditionally calling the code at runtime. The analyzer will recognize the new platform guards we added to System.OperatingSystem that you can use for checking.
public void PlayCMajor()
{
if (OperatingSystem.IsWindows())
{
// No diagnostic
Console.Beep(261, 1000);
}
}
You can also choose to mark your own APIs as being platform-specific, thus effectively just forwarding the requirements to your callers. You can only mark specific methods or types or the entire assembly.
[SupportedOSPlatform("platformName")] attribute to indicate that your API is platform-specific[SupportedOSPlatform("windows")]
public void PlayCMajor ()
{
// No diagnostics
Console.Beep(261, 1000);
}
Debug.Assert as a means for preventing the code from being reached on unsupported platforms. Using Debug.Assert allows the check to be trimmed out of release builds if desired.public void PlayCMajor()
{
Debug.Assert(OperatingSystem.IsWindows());
// No diagnostic
Console.Beep(261, 1000);
}
<NoWarn>, editor config, or #pragma): public void PlayCMajor ()
{
#pragma warning disable CA1416
Console.Beep(261, 1000);
#pragma warning restore CA1416
}
Core .NET libraries
We have applied [SupportedOSPlatform("windows")] attribute for some windows specific APIs. We also applied [UnsupportedOSPlatform("windows")] to the System.Security.Cryptography.OpenSsl assembly. We are applying [UnsupportedOSPlatform("browser")] for APIs that are not supported in Blazor WebAssembly (still in progress).
CC @jmarolf @mavasani @jeffhandley @terrajobst
I've slightly edited the wording, but it looks great. Thanks!
I've slightly edited the wording, but it looks great. Thanks!
Looks great, thanks!
@buyaa-n I edited to:
Debug.Assert. Can you specifically review that section please?@jmarolf One question for you... is it correct that the diagnostics could show up when targeting netstandard, or would targeting netstandard put you in Analysis Level 4 such that you wouldn't get diagnostics from this analyzer unless you opt in?
I'm referring to this part:
Note: No diagnostic is raised if the project is targeting windows (net5.0-windows), a diagnostic is raised if the project is targeting net5.0 or netstandard
Add the approach for using Debug.Assert. Can you specifically review that section please?
Looks good, thanks!
@jmarolf One question for you... is it correct that the diagnostics could show up when targeting
netstandard, or would targetingnetstandardput you in Analysis Level 4 such that you wouldn't get diagnostics from this analyzer unless you opt in?I'm referring to this part:
Note: No diagnostic is raised if the project is targeting windows (net5.0-windows), a diagnostic is raised if the project is targeting net5.0 or netstandard
I believe you're correct, by default only net5.0 and net5.0-windows are opted into the new analysis level.
I believe you're correct, by default only
net5.0andnet5.0-windowsare opted into the new analysis level.
I just verified that switching from net5.0 to netstandard2.1 made the diagnostic go away. I'll edit the description to fix that.
I updated the target framework block to be:
Note: A diagnostic is only raised if the project is targeting
net5.0and has anAnalysisLevelof5(the default fornet5.0projects). This also applies to multi-targeted projects. No diagnostic is raised if the project is targeting windows only (net5.0-windows), or if you are targetingnetstandardornetcoreapp. Therefore, existing projects will not encounter these diagnostics until they are updated to targetnet5.0.
@terrajobst / @jmarolf - Feel free to further wordsmith that if you'd like.
The remaining work is to list the APIs individually.
I think listing the APIs out individually has low value for the effort required, so I'm going to close this issue out now.
Most helpful comment
I just verified that switching from
net5.0tonetstandard2.1made the diagnostic go away. I'll edit the description to fix that.