Analysverktyg för plattformskompatibilitet

Du har förmodligen hört mottot "One .NET": en enda enhetlig plattform för att skapa alla typer av program. .NET 5 SDK innehåller ASP.NET Core, Entity Framework Core, WinForms, WPF, Xamarin och ML.NET och lägger till stöd för fler plattformar över tid. .NET 5 strävar efter att ge en upplevelse där du inte behöver resonera om de olika smakerna av .NET, men inte försöker att helt abstrahera bort det underliggande operativsystemet (OS). Du fortsätter att kunna anropa plattformsspecifika API:er, till exempel P/Invokes, WinRT eller Xamarin-bindningarna för iOS och Android.

Men att använda plattformsspecifika API:er på en komponent innebär att koden inte längre fungerar på alla plattformar. Vi behövde ett sätt att identifiera detta vid designtillfället så att utvecklare får diagnostik när de oavsiktligt använder plattformsspecifika API:er. För att uppnå det här målet introducerar .NET 5 plattformskompatibilitetsanalyseraren och kompletterande API:er för att hjälpa utvecklare att identifiera och använda plattformsspecifika API:er där det är lämpligt.

Bland de nya API:erna finns:

Förutsättningar

Analysverktyg för plattformskompatibilitet är en av analysverktygen för Roslyn-kodkvalitet. Från och med .NET 5 ingår dessa analysverktyg i .NET SDK. Analysatorn för plattformskompatibilitet är aktiverad som standard endast för projekt som är mål net5.0 eller en senare version. Du kan dock aktivera den för projekt som riktar in sig på andra ramverk.

Så här avgör analysatorn plattformsberoende

  • Ett icke-distribuerat API anses fungera på alla OS-plattformar.

  • Ett API som har markerats med [SupportedOSPlatform("platform")] anses endast vara portabelt till den angivna plattformen och alla plattformar som det är en delmängd av.

    • Attributet kan användas flera gånger för att indikera stöd för flera plattformar, till exempel [SupportedOSPlatform("windows"), SupportedOSPlatform("Android29.0")].
    • Om plattformen är en delmängd av en annan plattform innebär attributet att superuppsättningsplattformen också stöds. Innebär till exempel [SupportedOSPlatform("iOS")] att API:et stöds på iOS och även på dess superuppsättningsplattform, MacCatalyst.
    • Analysatorn ger en varning om plattformsspecifika API:er refereras utan någon lämplig plattformskontext:
      • Varnar om projektet inte riktar sig mot den plattform som stöds (till exempel ett Windows-specifikt API som anropas från ett projekt som riktar sig till iOS <TargetFramework>net5.0-ios14.0</TargetFramework>).
      • Varnar om projektet är plattformsoberoende och anropar plattformsspecifika API:er (till exempel ett Windows-specifikt API som anropas från plattformsoberoende TFM <TargetFramework>net5.0</TargetFramework>).
      • Varnar inte om det plattformsspecifika API:et refereras i ett projekt som riktar sig till någon av de angivna plattformarna (till exempel för ett Windows-specifikt API som anropas från ett projekt som riktar sig till fönster <TargetFramework>net5.0-windows</TargetFramework> och AssemblyInfo.cs filgenerering är aktiverad för projektet).
      • Varnar inte om det plattformsspecifika API-anropet är skyddat av motsvarande plattformskontrollmetoder (till exempel ett Windows-specifikt API-anrop som bevakas av OperatingSystem.IsWindows()).
      • Varnar inte om det plattformsspecifika API:et refereras från samma plattformsspecifika kontext (anropswebbplatsen tillskrivs också ).[SupportedOSPlatform("platform")
  • Ett API som markerats med [UnsupportedOSPlatform("platform")] anses inte ha stöd för den angivna plattformen och alla plattformar som det är en delmängd av, men stöds för alla andra plattformar.

    • Attributet kan användas flera gånger med olika plattformar, till exempel [UnsupportedOSPlatform("iOS"), UnsupportedOSPlatform("Android29.0")].
    • Om plattformen är en delmängd av en annan plattform innebär attributet att superuppsättningsplattformen inte heller stöds. Innebär till exempel [UnsupportedOSPlatform("iOS")] att API:et inte stöds på iOS och även på dess superuppsättningsplattform, MacCatalyst.
    • Analysatorn genererar endast en varning om den platform är effektiv för anropswebbplatsen:
      • Varnar om projektet riktar in sig på den plattform som tillskrivs som inte stöds (till exempel om API:et tillskrivs [UnsupportedOSPlatform("windows")] och anropswebbplatsens mål <TargetFramework>net5.0-windows</TargetFramework>).

      • Varnar om projektet är flera mål och platform ingår i standardgruppen MSBuild-objekt <SupportedPlatform> , eller om det platform ingår manuellt i MSBuild<objektgruppen SupportedPlatform> :

        <ItemGroup>
            <SupportedPlatform Include="platform" />
        </ItemGroup>
        
      • Varnar inte om du skapar en app som inte riktar sig till den plattform som inte stöds eller är flera mål och plattformen inte ingår i standardgruppen MSBuild-objekt <SupportedPlatform> .

  • Båda attributen kan instansieras med eller utan versionsnummer som en del av plattformsnamnet. Versionsnummer är i formatet major.minor[.build[.revision]]; major.minor krävs och build delarna och revision är valfria. "Windows6.1" anger till exempel Windows version 6.1, men "Windows" tolkas som Windows 0.0.

Mer information finns i exempel på hur attributen fungerar och vilken diagnostik de orsakar.

Så identifierar analysatorn TFM-målplattformar

Analysatorn kontrollerar inte målplattformen för målramverk (TFM) från MSBuild-egenskaper, till exempel <TargetFramework> eller <TargetFrameworks>. Om TFM har en målplattform matar MSBuild in ett SupportedOSPlatform attribut med målplattformsnamnet i AssemblyInfo.cs-filen, som används av analysatorn. Om TFM till exempel är net5.0-windows10.0.19041matar MSBuild in [assembly: System.Runtime.Versioning.SupportedOSPlatform("windows10.0.19041")] attributet i filen AssemblyInfo.cs och hela sammansättningen anses vara endast Windows. Därför skulle det inte orsaka några varningar i projektet att anropa API:er med endast Windows som är version 7.0 eller senare.

Kommentar

Om den AssemblyInfo.cs filgenereringen är inaktiverad för projektet (dvs <GenerateAssemblyInfo> . egenskapen är inställd på false) kan det obligatoriska sammansättningsnivåattributet SupportedOSPlatform inte läggas till av MSBuild. I det här fallet kan du se varningar för en plattformsspecifik API:er-användning även om du riktar in dig på den plattformen. Lös varningarna genom att aktivera AssemblyInfo.cs filgenerering eller lägga till attributet manuellt i projektet.

Plattformsinkludering

.NET 6 introducerar begreppet plattformsinkludering, där en plattform kan vara en delmängd av en annan plattform. En kommentar för delmängdsplattformen innebär samma stöd (eller brist på sådan) för superuppsättningsplattformen. Om en plattformskontrollmetod i OperatingSystem typen har ett SupportedOSPlatformGuard("supersetPlatform")] attribut anses den supersetPlatform vara en superuppsättning av os-plattformen som metoden söker efter.

Metoden tillskrivs OperatingSystem.IsIOS()[SupportedOSPlatformGuard("MacCatalyst")]till exempel . Därför gäller följande instruktioner:

  • Metoderna OperatingSystem.IsIOS() och OperatingSystem.IsIOSVersionAtLeast kontrollerar inte bara iOS plattformen, utan även MacCatalyst plattformen.
  • [SupportedOSPlatform("iOS")] innebär att API:et stöds på iOS och även på dess superuppsättningsplattform, MacCatalyst. Du kan använda attributet [UnsupportedOSPlatform("MacCatalyst")] för att undanta detta underförstådda stöd.
  • [UnsupportedOSPlatform("iOS") innebär att API:et inte stöds på iOS och MacCatalyst. Du kan använda [SupportedOSPlatform("MacCatalyst")] attributet för att utesluta denna underförstådda brist på support.

Tänk på följande täckningsmatris, där ✔️ anger att plattformen stöds och ❌ anger att plattformen inte stöds.

Plattform SupportedOSPlatform(subset) SupportedOSPlatform(superset) UnsupportedOSPlatform(subset) UnsupportedOSPlatform(superset)
Delmängd ✔️ ✔️
Superset ✔️ ✔️ ✔️ ✔️

Dricks

Samma regler gäller för attributen SupportedOSPlatformGuard och UnsupportedOSPlatformGuard .

Följande kodfragment visar hur du kan kombinera attribut för att ange rätt stödnivå.

  // 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() { }

Avancerade scenarier för attributkombinationer

  • Om en kombination av [SupportedOSPlatform] och [UnsupportedOSPlatform] attribut finns grupperas alla attribut efter OS-plattformsidentifierare:

    • Endast lista som stöds. Om den lägsta versionen för varje OS-plattform är ett [SupportedOSPlatform] attribut anses API:et endast stödjas av de listade plattformarna och stöds inte av alla andra plattformar. De valfria [UnsupportedOSPlatform] attributen för varje plattform kan bara ha högre version av den lägsta version som stöds, vilket anger att API:et tas bort från den angivna versionen.

      // 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();
      
    • Listan stöds inte. Om den lägsta versionen för varje OS-plattform är ett [UnsupportedOSPlatform] attribut anses API:et endast inte stödjas av de listade plattformarna och stöds av alla andra plattformar. Listan kan ha [SupportedOSPlatform] attribut med samma plattform men en högre version, vilket anger att API:et stöds från och med den versionen.

      // 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();
      
    • Inkonsekvent lista. Om den lägsta versionen för vissa plattformar är [SupportedOSPlatform] när den är [UnsupportedOSPlatform] för andra plattformar anses den vara inkonsekvent, vilket inte stöds för analysatorn. Om inkonsekvens inträffar ignorerar analysatorn plattformarna [UnsupportedOSPlatform] .

      • Om de lägsta versionerna av [SupportedOSPlatform] och [UnsupportedOSPlatform] attributen är lika med, betraktar analysatorn plattformen som en del av listan endast stöds.
  • Plattformsattribut kan tillämpas på typer, medlemmar (metoder, fält, egenskaper och händelser) och sammansättningar med olika plattformsnamn eller versioner.

    • Attribut som tillämpas på den översta nivån target påverkar alla dess medlemmar och typer.
    • Attribut på undernivå gäller endast om de följer regeln "underordnade anteckningar kan begränsa plattformsstödet, men de kan inte bredda det".
      • När överordnad endast har listan Stöds kan inte underordnade medlemsattribut lägga till ett nytt plattformsstöd, eftersom det skulle utöka det överordnade stödet. Stöd för en ny plattform kan bara läggas till i själva den överordnade plattformen. Men det underordnade kan ha Supported attributet för samma plattform med senare versioner eftersom det begränsar stödet. Dessutom kan det underordnade ha Unsupported attributet med samma plattform som det begränsar även överordnat stöd.
      • När den överordnade listan endast stöds kan underordnade medlemsattribut lägga till stöd för en ny plattform, eftersom det begränsar överordnat stöd. Men det kan inte ha Supported attributet för samma plattform som den överordnade, eftersom det utökar överordnat stöd. Stöd för samma plattform kan bara läggas till i den överordnade där det ursprungliga Unsupported attributet tillämpades.
    • Om [SupportedOSPlatform("platformVersion")] tillämpas mer än en gång för ett API med samma platform namn tar analysatorn bara hänsyn till den som har den lägsta versionen.
    • Om [UnsupportedOSPlatform("platformVersion")] används mer än två gånger för ett API med samma platform namn tar analysatorn bara hänsyn till de två med de tidigaste versionerna.

    Kommentar

    Ett API som stöds från början men som inte stöds (tas bort) i en senare version förväntas inte få återstöd i en senare version.

Exempel på hur attributen fungerar och vilken diagnostik de producerar

// 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();
}

Hantera rapporterade varningar

Det rekommenderade sättet att hantera den här diagnostiken är att se till att du bara anropar plattformsspecifika API:er när du kör på en lämplig plattform. Här följer de alternativ som du kan använda för att åtgärda varningarna. välj det som passar bäst för din situation:

  • Vakta samtalet. Du kan uppnå detta genom att villkorligt anropa koden vid körning. Kontrollera om du kör på önskad Platform genom att använda någon av metoderna för plattformskontroll, till exempel OperatingSystem.Is<Platform>() eller OperatingSystem.Is<Platform>VersionAtLeast(int major, int minor = 0, int build = 0, int revision = 0). Exempel.

  • Markera anropswebbplatsen som plattformsspecifik. Du kan också välja att markera dina egna API:er som plattformsspecifika, vilket i praktiken bara vidarebefordrar kraven till dina uppringare. Markera den innehållande metoden eller typen eller hela sammansättningen med samma attribut som det refererade plattformsberoende anropet. Exempel.

  • Kontrollera anropswebbplatsen med plattformskontroll. Om du inte vill ha mer omkostnader för en extra if instruktion vid körning använder du Debug.Assert(Boolean). Exempel.

  • Ta bort koden. Vanligtvis inte vad du vill eftersom det innebär att du förlorar återgivning när din kod används av Windows-användare. I fall där det finns ett plattformsoberoende alternativ är det förmodligen bättre att använda det via plattformsspecifika API:er.

  • Ignorera varningen. Du kan också helt enkelt ignorera varningen, antingen via en EditorConfig-post eller #pragma warning disable CA1416. Det här alternativet bör dock vara en sista utväg när du använder plattformsspecifika API:er.

    Dricks

    När du inaktiverar varningar med hjälp av #pragma förkompileringsdirektiven är de identifierare som du riktar in dig på skiftlägeskänsliga. Skulle till exempel ca1416 inte inaktivera varning CA1416.

Skydda plattformsspecifika API:er med skyddsmetoder

Guard-metodens plattformsnamn ska matcha med det anropande plattformsberoende API-plattformsnamnet. Om plattformssträngen för det anropande API:et innehåller versionen:

  • [SupportedOSPlatform("platformVersion")] För attributet ska guard-metodplattformen version vara större än eller lika med anropsplattformens Version.

  • [UnsupportedOSPlatform("platformVersion")] För attributet ska guard-metodens plattform version vara mindre än eller lika med den anropande plattformens 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
        }
    }
    
  • Om du behöver skydda kod som mål netstandard eller där nya OperatingSystem API:er inte är tillgängliga kan API:et RuntimeInformation.IsOSPlatform användas och kommer att respekteras netcoreapp av analysatorn. Men den är inte lika optimerad som de nya API:erna som lagts till i OperatingSystem. Om plattformen inte stöds i structen OSPlatform kan du anropa OSPlatform.Create(String) och skicka in plattformsnamnet, vilket analysatorn också respekterar.

    public void CallingSupportedOnlyApis()
    {
        if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
        {
            SupportedOnWindowsAndLinuxOnly(); // will not warn
        }
    
        if (RuntimeInformation.IsOSPlatform(OSPlatform.Create("browser")))
        {
            ApiOnlySupportedOnBrowser(); // call of browser specific API
        }
    }
    

Kommentera API:er med platform guard-attribut och använd dem som ett anpassat skydd

Som vi tidigare har visat känner analysatorn igen de statiska metoderna platform-guard i OperatingSystem typen, till exempel OperatingSystem.IsWindows, och även RuntimeInformation.IsOSPlatform. Men du kanske vill cachelagrat skyddsresultatet i ett fält och återanvända det, eller använda anpassade skyddsmetoder för att kontrollera en plattform. Analysatorn måste känna igen sådana API:er som en anpassad vakt och bör inte varna för de API:er som bevakas av dem. Skyddsattributen introducerades i .NET 6 för att stödja det här scenariot:

  • SupportedOSPlatformGuardAttribute kommenterar API:er som kan användas som skydd för API:er som kommenterats med SupportedOSPlatformAttribute.
  • UnsupportedOSPlatformGuardAttribute kommenterar API:er som kan användas som skydd för API:er som kommenterats med UnsupportedOSPlatformAttribute.

Dessa attribut kan också innehålla ett versionsnummer. De kan användas flera gånger för att skydda fler än en plattform och kan användas för att kommentera ett fält, en egenskap eller en metod.

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
        }
    }
}

Markera anropswebbplatsen som plattformsspecifik

Plattformsnamn ska matcha det anropande plattformsberoende API:et. Om plattformssträngen innehåller en version:

  • [SupportedOSPlatform("platformVersion")] För attributet ska anropswebbplatsplattformen version vara större än eller lika med den anropande plattformensVersion

  • [UnsupportedOSPlatform("platformVersion")] För attributet ska anropswebbplatsplattformen version vara mindre än eller lika med den anropande plattformensVersion

    // 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();
    }
    

Kontrollera anropsplatsen med plattformskontroll

Alla villkorsstyrda kontroller som används i platform guard-exemplen kan också användas som villkor för 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
}

Se även