Analyzátor kompatibility platformy

Pravděpodobně jste zaslechli "One .NET": jednu jednotnou platformu pro vytváření libovolného typu aplikace. Sada .NET 5.0 SDK zahrnuje ASP.NET Core, Entity Framework Core, WinForms, WPF, Xamarin a ML.NET a bude přidávat podporu pro další platformy v průběhu času. .NET 5.0 se snaží poskytnout prostředí, ve kterém nemusíte mít zdůvodnění o různých příchutích platformy .NET, ale nepokouší se úplně abstrahovat základní operační systém. Budete moct dál volat rozhraní API specifická pro platformu, jako jsou volání nespravování kódu, WinRT nebo vazby Xamarin pro iOS a Android.

Použití rozhraní API pro konkrétní platformu v komponentě ale znamená, že kód už nefunguje 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 platformu. K dosažení tohoto cíle zavádí .NET 5.0 analyzátor kompatibility platforem a doplňková rozhraní API, která vývojářům pomáhají v případě potřeby identifikovat a používat rozhraní API specifická pro platformu.

Mezi nová rozhraní API patří:

  • SupportedOSPlatformAttribute anotovat rozhraní API jako specifická pro platformu a anotovat rozhraní API jako nepodporovaná UnsupportedOSPlatformAttribute v konkrétním operačním systému. Tyto atributy mohou volitelně zahrnovat číslo verze a již byly použity na některá rozhraní API specifická 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 třídě pro bezpečné volání rozhraní API System.OperatingSystem specifických pro platformu. Můžete například použít k ochlazování volání rozhraní API specifického pro Windows a () lze použít k ochlazování ve verzích Windows volání OperatingSystem.IsWindows() OperatingSystem.IsWindowsVersionAtLeast rozhraní API specifického pro konkrétní rozhraní API. Podívejte se na tyto příklady použití těchto metod jako ochranného systému referencí rozhraní API specifických pro platformu.

Požadavky

Analyzátor kompatibility platformy je jedním z analyzátorů kvality kódu Roslyn. Od verze .NET 5.0 jsou tyto analyzátory obsažené v .NET SDK. Analyzátor kompatibility platformy je ve výchozím nastavení povolen pouze pro projekty, které cílí na nebo net5.0 novější verzi. Můžete ji ale povolit pro projekty, které cílí na jiné architektury.

Způsob, jakým analyzátor určuje závislost platformy

  • Rozhraní API bez atributu se považuje za pracovní na všech platformách operačního systému.
  • Rozhraní API označené se považuje za přenositelné pouze pro zadanou platformu a všechny platformy, které jsou [SupportedOSPlatform("platform")] 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 je podporována také platforma nadmnožiny. Například to znamená, že rozhraní API je podporováno na platformě [SupportedOSPlatform("iOS")] iOS nadmnožina a také na platformě MacCatalyst .
    • Analyzátor zobrazí upozornění, pokud se na rozhraní API specifické pro platformu odkazuje bez správného kontextu platformy:
      • Varuje, pokud se projekt nezaměřuje na podporovanou platformu (například rozhraní API specifické pro Windows z projektu, který cílí na <TargetFramework>net5.0-ios14.0</TargetFramework> iOS).
      • Varuje, pokud je projekt pro více platforem, a volá rozhraní API specifická pro platformu (například rozhraní API specifické Windows volat z TFM pro více <TargetFramework>net5.0</TargetFramework> platforem).
      • Neupozorní, pokud se na rozhraní API specifické pro platformu odkazuje v rámci projektu, který cílí na libovolnou ze zadaných platforem (například pro rozhraní API specifické pro Windows, které se volá z projektu cílení na windows <TargetFramework>net5.0-windows</TargetFramework> ).
      • Neupozorní, pokud je volání rozhraní API specifické pro platformu strážené odpovídajícími metodami kontroly platformy (například volání rozhraní API specifické Windows strážené OperatingSystem.IsWindows() ).
      • Neupozorní, pokud se na rozhraní API specifické pro platformu odkazuje ze stejného kontextu specifického pro platformu (web volání také s atributem [SupportedOSPlatform("platform") ).
  • Rozhraní API označené se považuje za nepodporované na zadané platformě a všech platformách, na které se používá, ale podporuje se [UnsupportedOSPlatform("platform")] pro všechny ostatní platformy.
    • Atribut lze použít několikrát u různých platforem, například [UnsupportedOSPlatform("iOS"), UnsupportedOSPlatform("Android29.0")] .
    • Pokud je platforma podmnožinou jiné platformy, atribut znamená, že platforma nadmnožiny není podporována. Například implikuje, že rozhraní API není podporováno na platformě nadmnožina , a také na [UnsupportedOSPlatform("iOS")] iOS platformě . MacCatalyst
    • Analyzátor zobrazí upozornění pouze v případě, že je pro lokalitu volání platform efektivní:
      • Varuje, pokud projekt cílí na platformu, která je přisuzována jako nepodporovaná (například pokud je rozhraní API atributované pomocí a [UnsupportedOSPlatform("windows")] web volání cílí na <TargetFramework>net5.0-windows</TargetFramework> ).

      • Varuje, pokud je projekt cílený na více než jeden a je zahrnutý ve výchozí platform <SupportedPlatform> MSBuild položek, nebo je ručně platform zahrnutý ve MSBuild <SupportedPlatform> skupině položek:

        <ItemGroup>
            <SupportedPlatform Include="platform" />
        </ItemGroup>
        
      • Neupozorní vás, pokud se seskupíte aplikaci, která není zaměřená na nepodporovanou platformu nebo je cílená na více platforem a která není součástí výchozí skupiny MSBuild <SupportedPlatform> položek.

  • V rámci názvu platformy je možné vytvořit instanci obou atributů s čísly verzí nebo bez nich. Čísla verzí jsou ve formátu major.minor[.build[.revision]] a jsou major.minor povinná a části a jsou build revision volitelné. Například "Windows7.0" označuje Windows verzi 7.0, 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ává cílové platformy TFM

Analyzátor neschová cílové monikery architektury (TFM) z MSBuild vlastností, jako je <TargetFramework> nebo <TargetFrameworks> . Pokud má TFM cílovou platformu, MSBuild vloží atribut s názvem cílové platformy v souboru SupportedOSPlatform AssemblyInfo.cs, který analyzátor využívá. Pokud je TFM například , MSBuild vloží atribut do souboru net5.0-windows [assembly: System.Runtime.Versioning.SupportedOSPlatform("windows7.0")] AssemblyInfo.cs a celé sestavení je považováno za Windows. Proto by Windows rozhraní API jen pro čtení s verzí 7.0 nebo nižší nezpůsobí v projektu žádná upozornění.

Poznámka

Pokud je generování souboru AssemblyInfo.cs pro projekt zakázané (to znamená, že vlastnost je nastavená na ), nelze požadovaný atribut na úrovni sestavení <GenerateAssemblyInfo> přidat pomocí false SupportedOSPlatform MSBuild. V takovém případě můžete vidět upozornění na využití rozhraní API pro konkrétní platformu i v případě, že cílíte na tuto platformu. Pokud chcete tato upozornění vyřešit, povolte generování souboru AssemblyInfo.cs nebo přidejte atribut do projektu ručně.

Zahrnutí platformy

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

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

  • Metody OperatingSystem.IsIOS() OperatingSystem.IsIOSVersionAtLeast a kontrolu používají nejen iOS platformu, ale také MacCatalyst platformu.
  • [SupportedOSPlatform("iOS")]znamená, že rozhraní API je podporováno na iOS platformě nadmnožina . MacCatalyst Tuto implicitní podporu [UnsupportedOSPlatform("MacCatalyst")] můžete vyloučit pomocí atributu .
  • [UnsupportedOSPlatform("iOS") znamená, že rozhraní API není podporováno v a iOS MacCatalyst . Tento implicitní nedostatek [SupportedOSPlatform("MacCatalyst")] podpory můžete vyloučit pomocí atributu .

Vezměte v úvahu následující matici pokrytí, kde ✔️ označuje, že je platforma podporovaná, a označuje, ❌ že platforma není podporovaná.

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

Tip

Stejná pravidla platí pro SupportedOSPlatformGuard atributy UnsupportedOSPlatformGuard a .

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 je k dispozici [SupportedOSPlatform] kombinace atributů a , jsou všechny [UnsupportedOSPlatform] atributy seskupeny podle identifikátoru platformy operačního systému:

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

      // API is only supported on Windows from version 8.0 to 10.0.19041.0 and all versions of Linux
      // The API is considered not supported for all other platforms.
      [SupportedOSPlatform("windows8.0")]
      [UnsupportedOSPlatform("windows10.0.19041.0")]
      [SupportedOSPlatform("linux")]
      public void ApiSupportedFromWindows80SupportFromCertainVersion();
      
    • Seznam pouze nepodporovaných položek Pokud je nejnižší verze pro každou platformu operačního systému atributem, pak se rozhraní API považuje za nepodporované pouze uvedenými platformami a podporované [UnsupportedOSPlatform] všemi ostatními platformami. Seznam může mít atribut se stejnou platformou, ale vyšší verzí, což značí, že rozhraní API se od této verze [SupportedOSPlatform] podporuje.

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

      • Pokud jsou nejnižší verze atributů a stejné, analyzátor považuje platformu za součást seznamu [SupportedOSPlatform] [UnsupportedOSPlatform] Pouze podporované.
  • Atributy platformy lze použít na typy, členy (metody, pole, vlastnosti a události) a sestavení s různými názvy nebo verzemi platformy.

    • Atributy použité na nejvyšší úrovni mají vliv na všechny jeho členy a target typy.
    • Atributy na podřízené úrovni se použijí jenom v případě, že dodržují pravidlo "podřízené poznámky mohou zúžit podporu platforem, ale nemohou ji rozšířit".
      • Pokud má nadřazená třída seznam Podporuje se pouze, pak atributy podřízeného členu nemohou přidat novou podporu platformy, protože by se tím rozšířila podpora nadřazených prvků. Podporu nové platformy je možné přidat pouze do samotné nadřazené platformy. Podřízený objekt ale může mít atribut pro stejnou platformu s novějšími verzemi, který Supported zúží podporu. Podřízený objekt může mít také atribut Unsupported se stejnou platformou, jako je ta, která také zužuje podporu nadřazených ovládacího prvku.
      • Pokud nadřazený prvek obsahuje seznam Pouze nepodporované, pak atributy podřízeného členu mohou přidat podporu pro novou platformu, protože se tím zúží podpora nadřazených prvků. Nemůže ale mít atribut pro stejnou platformu jako Supported nadřazená platforma, protože tím se rozšiřuje podpora nadřízené položky. Podporu pro stejnou platformu je možné přidat pouze do nadřazeného objektu, kde byl použit Unsupported původní atribut.
    • Pokud se pro rozhraní API se stejným názvem použije více než jednou, analyzátor zohlední pouze ten, který [SupportedOSPlatform("platformVersion")] platform má minimální verzi.
    • Pokud se pro rozhraní API se stejným názvem použije více než dvakrát, analyzátor zohlední pouze ty dvě s [UnsupportedOSPlatform("platformVersion")] platform nejstaršími verzemi.

    Poznámka

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

Příklady toho, jak atributy fungují a jakou diagnostiku vytvářejí

// 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 8.0 and later, not supported for all other.
// an API is removed/unsupported from version 10.0.19041.0.
[SupportedOSPlatform("windows8.0")]
[UnsupportedOSPlatform("windows10.0.19041.0")]
public void ApiSupportedFromWindows8UnsupportFromWindows10() { }

// 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. 'ApiSupportedFromWindows8UnsupportFromWindows10()' is only supported on: 'windows' from version 8.0 to 10.0.19041.0
    ApiSupportedFromWindows8UnsupportFromWindows10();

    // 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 8.0.
// The API is considered supported everywhere else without constraints.
[UnsupportedOSPlatform("windows")]
[SupportedOSPlatform("windows8.0")]
public void StartedWindowsSupportFromVersion8() { }

// an API was unsupported on Windows until version8.0.
// Then the API is removed (unsupported) from version 10.0.19041.0.
// The API is considered supported everywhere else without constraints.
[UnsupportedOSPlatform("windows")]
[SupportedOSPlatform("windows8.0")]
[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' 8.0 and before.
    StartedWindowsSupportFromVersion8();

    // This call site is reachable on all platforms. 'StartedWindowsSupportFrom8UnsupportedFrom10()' is supported on: 'windows' from version 8.0 to 10.0.19041.0
    StartedWindowsSupportFrom8UnsupportedFrom10();
}

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

Doporučeným způsobem, jak se s diagnostikou vypořádat, je ujistit se, že voláte rozhraní API specifická pro platformu pouze při spuštění na příslušné platformě. Toto jsou možnosti, které můžete použít k řešení upozornění. Zvolte to, které z těchto nastavení je pro vaši situaci nejvhodnější:

  • Chraňte volání. 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 nebo , zkontrolujte, jestli používáte Platform OperatingSystem.Is<Platform>() požadovanou OperatingSystem.Is<Platform>VersionAtLeast(int major, int minor = 0, int build = 0, int revision = 0) metodu. 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 platformu, a tím efektivně pouze předáte 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:

  • Zkontrolujte web volání pomocí kontroly platformy. Pokud nechcete režii dalšího příkazu if za běhu, použijte Debug.Assert(Boolean) . Příklad: .

  • Odstraňte kód. Obecně to není to, co chcete, protože to znamená, že ztratíte věrnost, když váš kód používají Windows uživatelé. V případech, kdy existuje alternativní řešení pro více platforem, je pravděpodobně lepší ji použít místo rozhraní API specifických pro platformu.

  • Potlačí upozornění. Upozornění můžete také jednoduše potlačit, 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žití rozhraní API specifických pro platformu.

    Tip

    Při zakazování upozornění pomocí direktiv před kompilátorem rozlišují identifikátory, na které cílíte, velká #pragma a malá písmena. Například by ca1416 ve skutečnosti nezaknul upozornění CA1416.

Rozhraní API specifická pro platformu Guard s metodami guard

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

  • Pro atribut by měla být platforma metod guard větší než nebo rovna platformě volání [SupportedOSPlatform("platformVersion")] version Version .

  • Pro atribut by platforma metody guard měla být menší nebo rovna platformě volání [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(8) && !OperatingSystem.IsWindowsVersionAtLeast(10.0.19041)))
        {
            ApiSupportedFromWindows8UnsupportFromWindows10();
        }
    
        if (OperatingSystem.IsWindowsVersionAtLeast(10, 0, 1903))
        {
            AssemblySupportedOnWindowsApiSupportedFromWindows10(); // Only need to check latest supported version
        }
    }
    
    public void CallingUnsupportedApis()
    {
        if (!OperatingSystem.IsAndroid())
        {
            DoesNotWorkOnAndroid(); // will not warn
        }
    
        if (!OperatingSystem.IsWindows() || OperatingSystem.IsWindowsVersionAtLeast(8))
        {
            StartedWindowsSupportFromVersion8(); // will not warn
        }
    
        if (!OperatingSystem.IsWindows() || // supported all other platforms
           (OperatingSystem.IsWindowsVersionAtLeast(8) && !OperatingSystem.IsWindowsVersionAtLeast(10, 0, 1903)))
        {
            StartedWindowsSupportFrom8UnsupportedFrom10(); // will not warn
        }
    }
    
  • Pokud potřebujete chránit kód, který cílí na rozhraní API nebo kde nejsou k dispozici nová rozhraní API, je možné rozhraní API použít a analyzátor ho netstandard netcoreapp bude OperatingSystem RuntimeInformation.IsOSPlatform respektovat. Není ale tak optimalizovaný jako nová rozhraní API přidaná v OperatingSystem . Pokud struktura platformu nepodporuje, můžete volat a předat název platformy, což analyzátor OSPlatform OSPlatform.Create(String) 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
        }
    }
    

Anotace rozhraní API s atributy ochrana platformy a jejich použití jako vlastní ochrana

Jak jsme si ukázali dříve, analyzátor rozpoznává statické metody ochranné platformy v typu, například OperatingSystem OperatingSystem.IsWindows , a také RuntimeInformation.IsOSPlatform . Můžete ale chtít do mezipaměti ukládat výsledek guard do pole a znovu ho použít, nebo použít vlastní metody guard pro kontrolu platformy. Analyzátor musí taková rozhraní API rozpoznat jako vlastní ochranu a neměl by upozorňovat na rozhraní API, která chrání. Atributy guard byly představeny v .NET 6 pro podporu tohoto scénáře:

  • SupportedOSPlatformGuardAttribute anotuje rozhraní API, která lze použít jako ochranu pro rozhraní API anotovaná pomocí SupportedOSPlatformAttribute .
  • UnsupportedOSPlatformGuardAttribute anotuje rozhraní API, která lze použít jako ochranu pro rozhraní API anotovaná pomocí UnsupportedOSPlatformAttribute .

Tyto atributy mohou volitelně obsahovat číslo verze. Lze je použít vícekrát pro ochranu více než jedné platformy a lze je použít k anotaci pole, vlastnosti nebo metody.

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čit web volání jako specifický pro platformu

Názvy platforem by měly odpovídat rozhraní API závislému na volající platformě. Pokud řetězec platformy obsahuje verzi:

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

  • U atributu by platforma lokality volání měla být menší nebo rovna [UnsupportedOSPlatform("platformVersion")] version 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 8.0 and later, not supported for all other.
    // an API is removed/unsupported from version 10.0.19041.0.
    [SupportedOSPlatform("windows8.0")]
    [UnsupportedOSPlatform("windows10.0.19041.0")]
    public void ApiSupportedFromWindows8UnsupportFromWindows10() { }
    
    // 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("windows8.0")] // call site attributed Windows 8.0 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("windows8.0")] attribute, but warns for [UnsupportedOSPlatform("windows10.0.19041.0")]
        // This call site is reachable on: 'windows' 8.0 and later. 'ApiSupportedFromWindows8UnsupportFromWindows10()' is unsupported on: 'windows' 10.0.19041.0 and later.
        ApiSupportedFromWindows8UnsupportFromWindows10();
    
        // The call site version is lower than the calling version, so warns:
        // This call site is reachable on: 'windows' 8.0 and later. 'AssemblySupportedOnWindowsApiSupportedFromWindows10()' is only supported on: 'windows' 10.0.19041.0 and later
        AssemblySupportedOnWindowsApiSupportedFromWindows10();
    }
    
    [SupportedOSPlatform("windows11.0")] // call site attributed with windows 11.0 or above.
    public void Caller2()
    {
        // This call site is reachable on: 'windows' 11.0 and later. 'ApiSupportedFromWindows8UnsupportFromWindows10()' is unsupported on: 'windows' 10.0.19041.0 and later.
        ApiSupportedFromWindows8UnsupportFromWindows10();
    
        // will not warn as call site version higher than calling API.
        AssemblySupportedOnWindowsApiSupportedFromWindows10();
    }
    
    [SupportedOSPlatform("windows8.0")]
    [UnsupportedOSPlatform("windows10.0.19041.0")] // call site supports Windows from version 8.0 to 10.0.19041.0.
    public void Caller3()
    {
        // will not warn as caller has exact same attributes.
        ApiSupportedFromWindows8UnsupportFromWindows10();
    
        // The call site reachable for the version not supported in the calling API, therefore warns:
        // This call site is reachable on: 'windows' from version 8.0 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 8.0.
    // The API is considered supported everywhere else without constraints.
    [UnsupportedOSPlatform("windows")]
    [SupportedOSPlatform("windows8.0")]
    public void StartedWindowsSupportFromVersion8() { }
    
    // an API was unsupported on Windows until version8.0.
    // Then the API is removed (unsupported) from version 10.0.19041.0.
    // The API is considered supported everywhere else without constraints.
    [UnsupportedOSPlatform("windows")]
    [SupportedOSPlatform("windows8.0")]
    [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();
    }
    

Vyhodnocení volání webu pomocí kontroly platformy

Všechny podmíněné kontroly použité v příkladech funkce platform guard je možné použít také 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é