Analyzátor kompatibility platformy

Pravděpodobně jste slyšeli heslo "One .NET": jedna sjednocená platforma pro vytváření libovolného typu aplikace. Sada .NET 5 SDK zahrnuje ASP.NET Core, Entity Framework Core, WinForms, WPF, Xamarin a ML.NET a v průběhu času přidá podporu pro další platformy. .NET 5 se snaží poskytnout prostředí, kde nemusíte mít důvod k různým příchutím .NET, ale nepokouší se plně abstrahovat základní operační systém (OS). Budete moct dál volat rozhraní API specifická pro platformu, například volání P/Invokes, WinRT nebo vazby Xamarinu pro iOS a Android.

Použití rozhraní API specifických pro platformu na komponentě ale znamená, že kód už nebude fungovat na všech platformách. Potřebovali jsme způsob, jak to zjistit v době návrhu, aby vývojáři získali diagnostiku, když neúmyslně používají rozhraní API specifická pro danou platformu. Pro dosažení tohoto cíle .NET 5 zavádí analyzátor kompatibility platformy a doplňková rozhraní API, která vývojářům pomáhají identifikovat a používat rozhraní API specifická pro platformu, pokud je to vhodné.

Mezi nová rozhraní API patří:

  • SupportedOSPlatformAttribute k přidávání poznámek k rozhraním API jako specifická pro platformu a UnsupportedOSPlatformAttribute k přidávání poznámek k rozhraním API, která nejsou podporována v konkrétním operačním systému. Tyto atributy mohou volitelně zahrnovat číslo verze a již byly použity u některých rozhraní API specifických pro platformu v základních knihovnách .NET.
  • Is<Platform>() a Is<Platform>VersionAtLeast(int major, int minor = 0, int build = 0, int revision = 0) statické metody ve System.OperatingSystem třídě pro bezpečné volání rozhraní API specifických pro platformu. Můžete například OperatingSystem.IsWindows() použít ochranu volání rozhraní API specifického pro Windows a OperatingSystem.IsWindowsVersionAtLeast() je možné použít k ochranu volání rozhraní API specifického pro windows ve verzi. Podívejte se na tyto příklady použití těchto metod jako stráží odkazů rozhraní API specifických pro platformu.

Požadavky

Analyzátor kompatibility platformy je jedním z analyzátorů kvality kódu Roslyn. Počínaje rozhraním .NET 5 jsou tyto analyzátory součástí sady .NET SDK. Analyzátor kompatibility platformy je ve výchozím nastavení povolen pouze pro projekty, které cílí net5.0 nebo novější verzi. Můžete ho ale povolit pro projekty, které cílí na jiné architektury.

Jak analyzátor určuje závislost platformy

  • Nepotřebné rozhraní API se považuje za funkční na všech platformách operačního systému.

  • Rozhraní API označené [SupportedOSPlatform("platform")] jako přenosné je považováno pouze za přenosnou na zadanou platformu a všechny platformy, které jsou podmnožinou.

    • Atribut lze použít vícekrát k označení podpory více platforem, například [SupportedOSPlatform("windows"), SupportedOSPlatform("Android29.0")].
    • Pokud je platforma podmnožinou jiné platformy, atribut znamená, že se podporuje i platforma nadmnožina. Například napovídá, [SupportedOSPlatform("iOS")] že rozhraní API je podporováno iOS i na jeho platformě nadmnožinou . MacCatalyst
    • Analyzátor vygeneruje upozornění , pokud se na rozhraní API specifická pro platformu odkazuje bez správného kontextu platformy:
      • Upozorní, pokud projekt necílit na podporovanou platformu (například rozhraní API specifické pro Windows volané z projektu, který cílí na iOS <TargetFramework>net5.0-ios14.0</TargetFramework>).
      • Varuje , pokud je projekt multiplatformní a volá rozhraní API specifická pro danou platformu (například rozhraní API specifické pro Windows volané z TFM <TargetFramework>net5.0</TargetFramework>pro různé platformy).
      • Varuje , pokud se na rozhraní API specifické pro platformu odkazuje v rámci projektu, který cílí na některou ze zadaných platforem (například pro rozhraní API specifické pro Windows volaného z oken <TargetFramework>net5.0-windows</TargetFramework> určených pro projekty a je pro projekt povolené generování souborů AssemblyInfo.cs ).
      • Varuje, pokud je volání rozhraní API specifické pro platformu chráněno odpovídajícími metodami kontroly platformy (například voláním OperatingSystem.IsWindows()rozhraní API specifického pro Windows).
      • Varuje, pokud se na rozhraní API specifické pro platformu odkazuje ze stejného kontextu specifického pro platformu (web volání je také přiřazen).[SupportedOSPlatform("platform")
  • Rozhraní API označené [UnsupportedOSPlatform("platform")] jako nepodporované na zadané platformě a všech platformách, které jsou podmnožinou, ale podporují se pro všechny ostatní platformy.

    • Atribut lze použít vícekrát s různými platformami, [UnsupportedOSPlatform("iOS"), UnsupportedOSPlatform("Android29.0")]například .
    • Pokud je platforma podmnožinou jiné platformy, atribut znamená, že platforma nadmnožina je také nepodporovaná. Například napovídá, [UnsupportedOSPlatform("iOS")] že rozhraní API není podporováno iOS a také na jeho nadmnožině platformy . MacCatalyst
    • Analyzátor vygeneruje upozornění pouze v případě, že platform je efektivní pro web volání:
      • Varuje , pokud projekt cílí na platformu, která je přiřazena jako nepodporovaná (například pokud je rozhraní API přiřazeno [UnsupportedOSPlatform("windows")] a cíl <TargetFramework>net5.0-windows</TargetFramework>webu volání).

      • Zobrazí upozornění, pokud je projekt více cílený a platform je zahrnutý ve výchozí skupině položek NÁSTROJE MSBuild<SupportedPlatform>nebo platform je ručně zahrnut do MSBuild<skupiny podporovaných položek>:

        <ItemGroup>
            <SupportedPlatform Include="platform" />
        </ItemGroup>
        
      • Varuje se , pokud vytváříte aplikaci, která necílí na nepodporovanou platformu nebo je více cílená a platforma není součástí výchozí skupiny položek NÁSTROJE MSBuild <SupportedPlatform> .

  • V rámci názvu platformy je možné vytvořit instanci obou atributů s čísly verzí nebo bez. Čísla verzí jsou ve formátu major.minor[.build[.revision]]; major.minor je povinná a buildrevision části jsou volitelné. Například "Windows6.1" označuje Windows verze 6.1, ale "Windows" se interpretuje jako Windows 0.0.

Další informace najdete v příkladech toho, jak atributy fungují a jakou diagnostiku způsobují.

Jak analyzátor rozpozná cílové platformy TFM

Analyzátor nekontroluje cílové platformy monikeru (TFM) cílové platformy z vlastností NÁSTROJE MSBuild, například <TargetFramework> nebo <TargetFrameworks>. Pokud má TFM cílovou platformu, nástroj MSBuild vloží SupportedOSPlatform do souboru AssemblyInfo.cs atribut s názvem cílové platformy, který analyzátor využívá. Pokud je net5.0-windows10.0.19041například TFM , nástroj MSBuild vloží [assembly: System.Runtime.Versioning.SupportedOSPlatform("windows10.0.19041")] atribut do souboru AssemblyInfo.cs a celé sestavení se považuje pouze za Windows. Proto volání rozhraní API jen pro Windows ve verzi 7.0 nebo novější nezpůsobí žádná upozornění v projektu.

Poznámka:

Pokud je generování souboru AssemblyInfo.cs pro projekt zakázáno (to znamená, že <GenerateAssemblyInfo> vlastnost je nastavena na false), požadovaný atribut úrovně SupportedOSPlatform sestavení nelze přidat nástrojem MSBuild. V takovém případě se zobrazí upozornění na využití rozhraní API specifická pro konkrétní platformu, i když na tuto platformu cílíte. Pokud chcete upozornění vyřešit, povolte generování AssemblyInfo.cs souboru nebo přidejte atribut do projektu ručně.

Zahrnutí platformy

.NET 6 představuje koncept začlenění platformy, kde jedna platforma může být podmnožinou jiné platformy. Poznámka pro platformu podmnožina znamená stejnou podporu (nebo její nedostatek) pro platformu nadmnožinou. Pokud metoda kontroly platformy v OperatingSystem typu má SupportedOSPlatformGuard("supersetPlatform")] atribut, pak supersetPlatform se považuje za nadmnožinu platformy operačního systému, kterou metoda kontroluje.

Například OperatingSystem.IsIOS() metoda je přiřazena [SupportedOSPlatformGuard("MacCatalyst")]. Proto platí následující příkazy:

  • Tyto OperatingSystem.IsIOS() metody OperatingSystem.IsIOSVersionAtLeast kontrolují nejen platformu iOS , ale také platformu MacCatalyst .
  • [SupportedOSPlatform("iOS")] znamená, že rozhraní API je podporováno iOS i na jeho nadmnožině platformy, MacCatalyst. Tento implicitní podporu můžete vyloučit pomocí atributu [UnsupportedOSPlatform("MacCatalyst")] .
  • [UnsupportedOSPlatform("iOS") znamená, že rozhraní API není podporováno iOS a MacCatalyst. Tento implicitní nedostatek podpory můžete vyloučit pomocí [SupportedOSPlatform("MacCatalyst")] atributu.

Podívejte se na následující matici pokrytí, kde ✔️ označuje, že platforma je podporovaná, a ❌ indikuje, že platforma není podporovaná.

Platforma SupportedOSPlatform(subset) SupportedOSPlatform(superset) UnsupportedOSPlatform(subset) UnsupportedOSPlatform(superset)
Podmnožina ✔️ ✔️
Nadmnožina ✔️ ✔️ ✔️ ✔️

Tip

Stejná pravidla platí pro atributy SupportedOSPlatformGuard a UnsupportedOSPlatformGuard atributy.

Následující fragment kódu ukazuje, jak můžete kombinovat atributy a nastavit správnou úroveň podpory.

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

Pokročilé scénáře pro kombinace atributů

  • Pokud existuje kombinace [SupportedOSPlatform] atributů a [UnsupportedOSPlatform] atributů, všechny atributy jsou seskupené podle identifikátoru platformy operačního systému:

    • Podporuje se jenom seznam. Pokud je nejnižší verze pro každou platformu [SupportedOSPlatform] operačního systému atributem, rozhraní API se považuje za podporované pouze uvedenými platformami a nepodporované všemi ostatními platformami. Volitelné [UnsupportedOSPlatform] atributy pro každou platformu můžou mít pouze vyšší verzi minimální podporované verze, která označuje, že rozhraní API je odebrané od zadané verze.

      // 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();
      
    • Nepodporovaný jenom seznam. Pokud je nejnižší verze pro každou platformu [UnsupportedOSPlatform] operačního systému atributem, rozhraní API se považuje za nepodporované pouze pro uvedené platformy a podporované všemi ostatními platformami. Seznam může mít [SupportedOSPlatform] atribut se stejnou platformou, ale vyšší verzí, což značí, že rozhraní API je podporováno od této verze.

      // 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();
      
    • Nekonzistentní seznam Pokud je [SupportedOSPlatform] nejnižší verze pro některé platformy v době, kdy se jedná [UnsupportedOSPlatform] o jiné platformy, považuje se za nekonzistentní, což není podporováno pro analyzátor. Pokud dojde k nekonzistence, analyzátor platformy ignoruje [UnsupportedOSPlatform] .

      • Pokud jsou nejnižší verze [SupportedOSPlatform] a [UnsupportedOSPlatform] atributy stejné, analyzátor považuje platformu za součást pouze seznamu Podporovaný.
  • Atributy platformy lze použít u typů, členů (metod, polí, vlastností a událostí) a sestavení s různými názvy nebo verzemi platformy.

    • Atributy použité na nejvyšší úrovni target ovlivňují všechny jeho členy a typy.
    • Atributy na úrovni podřízené úrovně se použijí pouze v případě, že dodržují pravidlo "podřízené poznámky můžou zúžit podporu platforem, ale nemůžou ho rozšířit".
      • Pokud nadřazený seznam obsahuje pouze seznam Podporovaný, atributy podřízeného člena nemůžou přidat novou podporu platformy, protože by se tím rozšiřovala nadřazená podpora. Podporu nové platformy je možné přidat pouze do nadřazeného objektu. Podřízená položka ale může mít Supported atribut pro stejnou platformu s novějšími verzemi, protože zúží podporu. Podřízená položka může mít Unsupported také atribut se stejnou platformou, jako má také zúžení nadřazené podpory.
      • Pokud nadřazený seznam obsahuje pouze nepodporovaný seznam, můžou atributy podřízeného člena přidat podporu pro novou platformu, protože tím se zužuje nadřazená podpora. Nemůže ale mít Supported atribut pro stejnou platformu jako nadřazený objekt, protože rozšiřuje podporu nadřazených objektů. Podporu pro stejnou platformu je možné přidat pouze do nadřazeného objektu, kde byl použit původní Unsupported atribut.
    • Pokud [SupportedOSPlatform("platformVersion")] se pro rozhraní API se stejným platform názvem použije více než jednou, analyzátor považuje pouze ten s minimální verzí.
    • Pokud [UnsupportedOSPlatform("platformVersion")] je pro rozhraní API se stejným platform názvem použito více než dvakrát, analyzátor tyto dvě verze považuje pouze za nejstarší verze.

    Poznámka:

    U rozhraní API, které se původně podporovalo, ale nepodporované (odebrané) v novější verzi, se neočekává, že se v novější verzi znovu podporuje.

Příklady fungování atributů a jejich diagnostiky

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

Zpracování ohlášených upozornění

Doporučeným způsobem řešení těchto diagnostik je zajistit, abyste při spouštění na příslušné platformě volali pouze rozhraní API specifická pro danou platformu. Níže jsou uvedené možnosti, které můžete použít k řešení upozornění; zvolte, která možnost je nejvhodnější pro vaši situaci:

  • Hlídejte hovor. Toho můžete dosáhnout podmíněným voláním kódu za běhu. Pomocí jedné z metod kontroly platformy, například pomocí metody kontroly platformy, nebo OperatingSystem.Is<Platform>VersionAtLeast(int major, int minor = 0, int build = 0, int revision = 0)zkontrolujte, OperatingSystem.Is<Platform>() jestli běžíte na požadovaném Platform počítači. Příklad:

  • Označte web volání jako specifický pro platformu. Můžete se také rozhodnout, že vlastní rozhraní API označíte jako specifická pro konkrétní platformu, a tím účinně přesměrujete požadavky volajícím. Označte obsahující metodu nebo typ nebo celé sestavení se stejnými atributy jako odkazované volání závislé na platformě. Příklady.

  • Pomocí kontroly platformy ověřte web volání. Pokud nechcete režijní náklady na další if příkaz za běhu, použijte Debug.Assert(Boolean). Příklad:

  • Odstraňte kód. Obecně není to, co chcete, protože to znamená, že ztratíte věrnost, když kód používají uživatelé Windows. V případech, kdy existuje multiplatformní alternativa, pravděpodobně lépe použijete rozhraní API specifická pro danou platformu.

  • Potlačí upozornění. Můžete také jednoduše potlačit upozornění, a to buď prostřednictvím položky EditorConfig , nebo #pragma warning disable CA1416. Tato možnost by ale měla být poslední možností při používání rozhraní API specifických pro platformu.

    Tip

    Při zakazování upozornění pomocí #pragma direktiv prekompilátoru se v identifikátorech, na které cílíte, rozlišují malá a velká písmena. Například ca1416 by ve skutečnosti nezakazoval upozornění CA1416.

Ochrana rozhraní API specifických pro platformu pomocí metod ochrany

Název platformy metody guard by se měl shodovat s názvem platformy závislého na platformě. Pokud řetězec platformy volajícího rozhraní API obsahuje verzi:

  • [SupportedOSPlatform("platformVersion")] Pro atribut by měla být platforma version ochranné metody větší nebo rovna volající platformě Version.

  • [UnsupportedOSPlatform("platformVersion")] Pro atribut by měla být platforma version ochranné metody menší nebo rovna volající platformě 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
        }
    }
    
  • Pokud potřebujete chránit kód, který cílí netstandard nebo netcoreapp kde nejsou k dispozici nová OperatingSystem rozhraní API, RuntimeInformation.IsOSPlatform můžete rozhraní API použít a bude respektovat analyzátor. Ale není tak optimalizovaná jako nová rozhraní API přidaná do OperatingSystem. Pokud se platforma ve OSPlatform struktuře nepodporuje, můžete volat OSPlatform.Create(String) a předávat název platformy, který analyzátor také respektuje.

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

Přidávání poznámek k rozhraním API pomocí atributů ochrany platformy a jejich použití jako vlastní ochrany

Jak je znázorněno výše, analyzátor rozpozná statické metody ochrany platformy v OperatingSystem typu, například OperatingSystem.IsWindows, a také RuntimeInformation.IsOSPlatform. Můžete ale chtít uložit výsledek ochrany do mezipaměti v poli a znovu ho použít nebo použít vlastní metody ochrany pro kontrolu platformy. Analyzátor musí tato rozhraní API rozpoznat jako vlastní stráž a neměl by varovat rozhraní API, která jsou chráněná. Atributy ochrany byly zavedeny v .NET 6 pro podporu tohoto scénáře:

  • SupportedOSPlatformGuardAttribute anotuje rozhraní API, která se dají použít jako ochrana pro rozhraní API anotovaná SupportedOSPlatformAttributepomocí .
  • UnsupportedOSPlatformGuardAttribute anotuje rozhraní API, která se dají použít jako ochrana pro rozhraní API anotovaná UnsupportedOSPlatformAttributepomocí .

Tyto atributy můžou volitelně obsahovat číslo verze. Lze je použít vícekrát pro ochranu více než jedné platformy a lze je použít k přidávání poznámek k poli, vlastnosti nebo 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
        }
    }
}

Označení webu volání jako specifického pro platformu

Názvy platforem by se měly shodovat s rozhraním API závislým na volající platformě. Pokud řetězec platformy obsahuje verzi:

  • U atributu [SupportedOSPlatform("platformVersion")] by měla být platforma version lokality volání větší nebo rovna volající platformě. Version

  • U atributu [UnsupportedOSPlatform("platformVersion")] by platforma version lokality volání měla být menší nebo rovna volající platformě. 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();
    }
    

Ověření lokality volání pomocí kontroly platformy

Všechny podmíněné kontroly použité v příkladech ochrany platformy lze také použít jako podmínku pro 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
}

Viz také