Platformkompatibilitás-elemző

Valószínűleg hallotta a "One .NET" mottóját: egyetlen, egységes platform bármilyen típusú alkalmazás létrehozásához. A .NET 5 SDK tartalmazza ASP.NET Core, Entity Framework Core, WinForms, WPF, Xamarin és ML.NET, és idővel több platformot is támogat. A .NET 5 arra törekszik, hogy olyan élményt nyújtson, ahol nem kell okokat szolgáltatnia a .NET különböző ízeire, de nem próbálja teljesen absztrakcióra használni az alapul szolgáló operációs rendszert (OS). Továbbra is meghívhat platformspecifikus API-kat, például P/Invokes, WinRT vagy xamarin kötéseket iOS és Android rendszeren.

A platformspecifikus API-k összetevőn való használata azonban azt jelenti, hogy a kód már nem működik az összes platformon. Szükség volt egy módszerre a tervezéskor, hogy a fejlesztők diagnosztikát kapnak, amikor véletlenül platformspecifikus API-kat használnak. E cél elérése érdekében a .NET 5 bevezeti a platformkompatibilitás-elemzőt és a kiegészítő API-kat, amelyek segítenek a fejlesztőknek azonosítani és használni a platformspecifikus API-kat, ahol szükséges.

Az új API-k a következők:

  • SupportedOSPlatformAttribute az API-k platformspecifikusként való megjegyzése, valamint UnsupportedOSPlatformAttribute az API-k megjegyzése, mivel azok nem támogatottak egy adott operációs rendszeren. Ezek az attribútumok opcionálisan magukban foglalhatják a verziószámot, és már alkalmazták őket az alapvető .NET-kódtárak platformspecifikus API-jaira.
  • Is<Platform>() és Is<Platform>VersionAtLeast(int major, int minor = 0, int build = 0, int revision = 0) statikus metódusok az osztályban a System.OperatingSystem platformspecifikus API-k biztonságos meghívásához. Használható például OperatingSystem.IsWindows() egy Windows-specifikus API-ra irányuló hívások őrzésére, és OperatingSystem.IsWindowsVersionAtLeast() egy verziószámozott Windows-specifikus API-hívás őrzésére. Tekintse meg ezeket a példákat arra, hogyan használhatók ezek a módszerek platformspecifikus API-hivatkozások őreiként.

Előfeltételek

A platformkompatibilitás-elemző a Roslyn-kódminőség-elemzők egyike. A .NET 5-től kezdve ezek az elemzők a .NET SDK részét képezik. A platformkompatibilitás-elemző alapértelmezés szerint csak a megcélzott net5.0 vagy újabb verziójú projektek esetében engedélyezett. Más keretrendszereket célzó projektek esetében azonban engedélyezheti.

Hogyan határozza meg az elemző a platformfüggőséget?

  • A nem támogatott API-k minden operációsrendszer-platformon működnek.

  • A megjelölt API-k [SupportedOSPlatform("platform")] csak a megadott platformon hordozhatónak tekinthetők, és minden olyan platformon, amelynek egy részhalmaza.

    • Az attribútum többször is alkalmazható több platform támogatásának jelzésére, például[SupportedOSPlatform("windows"), SupportedOSPlatform("Android29.0")].
    • Ha a platform egy másik platform részhalmaza, az attribútum azt jelenti, hogy a szuperhalmazplatform is támogatott. Ez azt jelenti például, [SupportedOSPlatform("iOS")] hogy az API támogatott a szuperhalmazplatformon iOS is. MacCatalyst
    • Az elemző figyelmeztetést küld, ha a platformspecifikus API-kra megfelelő platformkörnyezet nélkül hivatkoznak:
      • Figyelmeztet, ha a projekt nem a támogatott platformot célozza (például egy iOS-t <TargetFramework>net5.0-ios14.0</TargetFramework>célzó projektből hívott Windows-specifikus API- t).
      • Figyelmeztet, ha a projekt platformfüggetlen, és platformspecifikus API-kat hív meg (például egy Platformfüggetlen TFM-ről <TargetFramework>net5.0</TargetFramework>hívott Windows-specifikus API-t).
      • Nem figyelmeztet, ha a platformspecifikus API-ra olyan projekten belül hivatkozik, amely a megadott platformok bármelyikét célozza (például egy Windows-specifikus API-t, amelyet egy windowsos <TargetFramework>net5.0-windows</TargetFramework> projekt hív meg, és a AssemblyInfo.cs fájllétrehozás engedélyezve van a projekthez).
      • Nem figyelmeztet, ha a platformspecifikus API-hívást megfelelő platformellenőrzési metódusok védik (például egy Windows-specifikus API-hívást).OperatingSystem.IsWindows()
      • Nem figyelmeztet, ha a platformspecifikus API-ra ugyanabból a platformspecifikus környezetből hivatkozik (a hívási hely is hozzá van rendelve[SupportedOSPlatform("platform")).
  • A megjelölt [UnsupportedOSPlatform("platform")] API-k a megadott platformon és bármely platformon nem támogatottak, de az összes többi platform esetében támogatottak.

    • Az attribútum több alkalommal is alkalmazható különböző platformokon, például [UnsupportedOSPlatform("iOS"), UnsupportedOSPlatform("Android29.0")].
    • Ha a platform egy másik platform részhalmaza, az attribútum azt jelenti, hogy a szuperhalmazplatform szintén nem támogatott. Ez azt jelenti például, [UnsupportedOSPlatform("iOS")] hogy az API nem támogatott a iOS szuperhalmazplatformon és annak szuperhalmazplatformján is. MacCatalyst
    • Az elemző csak akkor állít elő figyelmeztetést, ha a platform híváshely érvényes:
      • Figyelmezteti , ha a projekt a nem támogatottnak tulajdonított platformot célozza meg (például ha az API-t [UnsupportedOSPlatform("windows")] hozzárendelték, és a híváshely céljait <TargetFramework>net5.0-windows</TargetFramework>).

      • Figyelmeztet, ha a projekt több célzott, és az platform alapértelmezett MSBuild <SupportedPlatform> elemcsoport része, vagy manuálisan platform szerepel a MSBuild<Támogatottplatform-elemek> csoportjában:

        <ItemGroup>
            <SupportedPlatform Include="platform" />
        </ItemGroup>
        
      • Nem figyelmeztet , ha olyan alkalmazást készít, amely nem a nem támogatott platformot célozza, vagy több célzott, és a platform nem szerepel az alapértelmezett MSBuild <SupportedPlatform> elemek csoportjában.

  • Mindkét attribútum példányosítható verziószámmal vagy anélkül a platformnév részeként. A verziószámok formátuma major.minor[.build[.revision]]kötelező, major.minor és az buildrevision alkatrészek nem kötelezőek. A "Windows6.1" például a Windows 6.1-es verzióját jelzi, a "Windows" azonban Windows 0.0-ként van értelmezve.

További információ: példák az attribútumok működésére és az általuk okozott diagnosztikára.

Hogyan ismeri fel az elemző a TFM-célplatformokat?

Az elemző nem ellenőrzi a cél-keretrendszer-moniker (TFM) célplatformokat az MSBuild tulajdonságokból, például <TargetFramework> vagy <TargetFrameworks>. Ha a TFM célplatformmal rendelkezik, az MSBuild egy attribútumot injektál SupportedOSPlatform a célplatform nevével a AssemblyInfo.cs fájlban, amelyet az elemző használ. Ha például a TFM az net5.0-windows10.0.19041, az [assembly: System.Runtime.Versioning.SupportedOSPlatform("windows10.0.19041")] MSBuild az attribútumot a AssemblyInfo.cs fájlba injektálja, és a teljes szerelvény csak Windows-nak minősül. Ezért a csak a 7.0-s vagy újabb verziójú Windows API-k meghívása nem okoz figyelmeztetést a projektben.

Feljegyzés

Ha a AssemblyInfo.cs fájlgenerálás le van tiltva a projektben (azaz a <GenerateAssemblyInfo> tulajdonság falseértéke), a szükséges szerelvényszintű SupportedOSPlatform attribútumot az MSBuild nem tudja hozzáadni. Ebben az esetben a platformspecifikus API-k használatára vonatkozó figyelmeztetések akkor is megjelenhetnek, ha a platformot célozza. A figyelmeztetések feloldásához engedélyezze a AssemblyInfo.cs fájlgenerálást, vagy adja hozzá manuálisan az attribútumot a projekthez.

Platformbefoglalás

A .NET 6 bevezeti a platformbefoglalás fogalmát, ahol az egyik platform egy másik platform részhalmaza lehet. Az alhalmazplatform széljegyzetei ugyanazt a támogatást (vagy annak hiányát) jelentik a szuperhalmazplatform esetében. Ha a típusban egy OperatingSystem platformellenőrzési módszer attribútummal rendelkezik SupportedOSPlatformGuard("supersetPlatform")] , akkor supersetPlatform az operációsrendszer-platform azon szuperhalmazának minősül, amelyet a metódus ellenőriz.

Például a OperatingSystem.IsIOS() metódus attribútuma [SupportedOSPlatformGuard("MacCatalyst")]. Ezért a következő utasítások érvényesek:

  • A OperatingSystem.IsIOS() metódusok nemcsak OperatingSystem.IsIOSVersionAtLeast a platformot, hanem a iOS platformot is ellenőrzik MacCatalyst .
  • [SupportedOSPlatform("iOS")] azt jelenti, hogy az API támogatott a iOS szuperhalmazplatformján is, MacCatalyst. Az attribútummal kizárhatja ezt a [UnsupportedOSPlatform("MacCatalyst")] vélelmezett támogatást.
  • [UnsupportedOSPlatform("iOS") azt jelenti, hogy az API nem támogatott és iOSMacCatalyst. Az attribútum használatával kizárhatja ezt a [SupportedOSPlatform("MacCatalyst")] vélelmezett támogatást.

Vegye figyelembe a következő lefedettségi mátrixot, amely ✔️ azt jelzi, hogy a platform támogatott, és ❌ azt jelzi, hogy a platform nem támogatott.

Platform SupportedOSPlatform(subset) SupportedOSPlatform(superset) UnsupportedOSPlatform(subset) UnsupportedOSPlatform(superset)
Részhalmazát ✔️ ✔️
Felülbírálja ✔️ ✔️ ✔️ ✔️

Tipp.

Ugyanezek a szabályok vonatkoznak az és UnsupportedOSPlatformGuard az SupportedOSPlatformGuard attribútumokra is.

Az alábbi kódrészlet bemutatja, hogyan kombinálhatja az attribútumokat a megfelelő támogatási szint beállításához.

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

Speciális forgatókönyvek attribútumkombinációkhoz

  • Ha az attribútumok és [UnsupportedOSPlatform] az [SupportedOSPlatform] attribútumok kombinációja van jelen, az összes attribútum az operációs rendszer platformazonosítója szerint van csoportosítva:

    • Csak támogatott lista. Ha az egyes operációsrendszer-platformok legalacsonyabb verziója egy [SupportedOSPlatform] attribútum, az API-t csak a felsorolt platformok támogatják, és az összes többi platform nem támogatja. Az egyes platformok opcionális [UnsupportedOSPlatform] attribútumai csak a minimálisan támogatott verzió magasabb verziójával rendelkezhetnek, ami azt jelzi, hogy az API a megadott verziótól kezdve el lett távolítva.

      // 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();
      
    • Nem támogatott csak lista. Ha az egyes operációsrendszer-platformok legalacsonyabb verziója egy [UnsupportedOSPlatform] attribútum, akkor az API-t csak a felsorolt platformok nem támogatják, és az összes többi platform támogatja. A lista rendelkezhet [SupportedOSPlatform] ugyanahhoz a platformhoz tartozó attribútummal, de egy magasabb verzióval, ami azt jelzi, hogy az API az adott verziótól kezdve támogatott.

      // 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();
      
    • Inkonzisztens lista. Ha egyes platformok [SupportedOSPlatform] legalacsonyabb verziója más platformok esetében van [UnsupportedOSPlatform] , akkor inkonzisztensnek minősül, ami az elemző számára nem támogatott. Inkonzisztencia esetén az elemző figyelmen kívül hagyja a [UnsupportedOSPlatform] platformokat.

      • Ha a legalacsonyabb verziók [SupportedOSPlatform] és [UnsupportedOSPlatform] attribútumok egyenlőek, az elemző a platformot csak a támogatott lista részeként tekinti.
  • A platformattribútumok különböző platformnevekkel vagy -verziókkal rendelkező típusokra, tagokra (metódusokra, mezőkre, tulajdonságokra és eseményekre) és szerelvényekre alkalmazhatók.

    • A felső szinten target alkalmazott attribútumok az összes tagot és típust érintik.
    • A gyermekszintű attribútumok csak akkor érvényesek, ha betartják a "gyermekjegyzetek szűkíthetik a platformok támogatását, de nem szélesíthetik" szabályt.
      • Ha a szülő csak támogatott listát tartalmaz, akkor a gyermektag-attribútumok nem adhatnak hozzá új platformtámogatást, mivel az a szülőtámogatás kiterjesztését jelentené. Az új platform támogatása csak a szülőhöz adható hozzá. A gyermek azonban rendelkezhet ugyanahhoz a Supported platformhoz tartozó attribútummal, a későbbi verziókkal, amelyek szűkítik a támogatást. Emellett a gyermek ugyanazzal a Unsupported platformmal rendelkezhet az attribútummal, mint amely a szülőtámogatást is szűkíti.
      • Ha a szülő nem támogatott csak listával rendelkezik, akkor a gyermektag attribútumok támogatást adhatnak egy új platformhoz, mivel ez szűkíti a szülőtámogatást. De nem rendelkezhet az Supported attribútummal ugyanahhoz a platformhoz, mint a szülő, mert ez kiterjeszti a szülőtámogatást. Ugyanannak a platformnak a támogatása csak az eredeti Unsupported attribútumot alkalmazó szülőhöz adható hozzá.
    • Ha [SupportedOSPlatform("platformVersion")] egy azonos platform nevű API-t többször alkalmaz, az elemző csak a minimális verziójút veszi figyelembe.
    • Ha [UnsupportedOSPlatform("platformVersion")] az azonos platform nevű API-k esetében több mint kétszer alkalmazzák, az elemző csak a legkorábbi verziókkal rendelkező kettőt veszi figyelembe.

    Feljegyzés

    Az eredetileg támogatott, de egy későbbi verzióban nem támogatott (eltávolított) API-k várhatóan nem lesznek újra támogatottak egy még későbbi verzióban.

Példák az attribútumok működésére és az általuk előállított diagnosztikára

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

Jelentett figyelmeztetések kezelése

A diagnosztika kezelésének ajánlott módja, hogy a megfelelő platformon való futtatáskor csak platformspecifikus API-kat hívjon meg. A következő lehetőségeket használhatja a figyelmeztetések kezelésére; válassza ki a helyzetének leginkább megfelelőt:

  • Őrizd meg a hívást. Ezt úgy érheti el, hogy futtatáskor feltételesen meghívja a kódot. Ellenőrizze, hogy a kívánt Platform módon fut-e például a platformellenőrzési módszerek egyikével. OperatingSystem.Is<Platform>()OperatingSystem.Is<Platform>VersionAtLeast(int major, int minor = 0, int build = 0, int revision = 0) Példa:

  • Jelölje meg a híváswebhelyet platformspecifikusként. Dönthet úgy is, hogy a saját API-kat platformspecifikusként jelöli meg, így hatékonyan továbbítja a követelményeket a hívóknak. Jelölje meg a tartalmazó metódust vagy típust vagy a teljes szerelvényt ugyanazokkal az attribútumokkal, mint a hivatkozott platformfüggő hívás. Példák.

  • A hívás helyének érvényesítése platformellenőrzéssel. Ha nem szeretné, hogy futásidőben további if utasítás többletterhelése legyen, használja a következőt Debug.Assert(Boolean): Példa:

  • Törölje a kódot. Általában nem az, amit szeretne, mert ez azt jelenti, hogy elveszíti a hűséget, amikor a kódot a Windows-felhasználók használják. Platformfüggetlen alternatíva esetén valószínűleg jobb, ha ezt platformspecifikus API-kon keresztül használja.

  • Tiltsa le a figyelmeztetést. A figyelmeztetést egyszerűen letilthatja egy EditorConfig bejegyzéssel vagy #pragma warning disable CA1416. Ennek a lehetőségnek azonban végső megoldásnak kell lennie platformspecifikus API-k használatakor.

    Tipp.

    Ha letiltja a figyelmeztetéseket az #pragma előfordítási irányelvek használatával, a megcélzott azonosítók megkülönböztetik a kis- és nagybetűket. Például ca1416 nem tiltaná le a CA1416 figyelmeztetést.

Platformspecifikus API-k őrzési módszerekkel

Az őr metódus platformnevének meg kell egyeznie a hívó platformfüggetlen API-platform nevével. Ha a hívó API platformsztringje tartalmazza a verziót:

  • Az attribútum esetében az [SupportedOSPlatform("platformVersion")] őrmetódus platformjának version nagyobbnak vagy egyenlőnek kell lennie a hívó platforménál Version.

  • Az attribútum esetében az [UnsupportedOSPlatform("platformVersion")] őr metódus platformjának version kisebbnek vagy egyenlőnek kell lennie a hívó platforménál 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
        }
    }
    
  • Ha meg kell őriznie azokat OperatingSystem a kódot, amelyek célja netstandard vagy netcoreapp új API-k nem érhetők el, az RuntimeInformation.IsOSPlatform API-t használhatja, és az elemző tiszteletben fogja tartani. De ez nem olyan optimalizált, mint az új API-k hozzáadott OperatingSystem. Ha a platform nem támogatott a OSPlatform szerkezetben, meghívhatja OSPlatform.Create(String) és átadhatja a platform nevét, amelyet az elemző is tiszteletben tart.

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

Api-k jegyzetelése platformőr attribútumokkal, és egyéni védőként való használata

Ahogy korábban már láthattuk, az elemző felismeri a platformőr statikus metódusokat a OperatingSystem típusban, például OperatingSystem.IsWindows, és azt is RuntimeInformation.IsOSPlatform. Előfordulhat azonban, hogy gyorsítótárazni szeretné az őr eredményét egy mezőben, és újra felhasználja azt, vagy egyéni védőmetszeteket használ egy platform ellenőrzéséhez. Az elemzőnek egyéni védőként kell felismernie az ilyen API-kat, és nem szabad figyelmeztetnie az általuk őrzött API-kat. A .NET 6-ban bevezettük a védőattribútumokat a forgatókönyv támogatásához:

  • SupportedOSPlatformGuardAttribute annotates API-k, amelyek védőként használhatók a következővel SupportedOSPlatformAttributejegyzetelt API-khoz: .
  • UnsupportedOSPlatformGuardAttribute annotates API-k, amelyek védőként használhatók a következővel UnsupportedOSPlatformAttributejegyzetelt API-khoz: .

Ezek az attribútumok opcionálisan tartalmazhatnak verziószámot. Ezek többször is alkalmazhatók több platform őrzésére, és használhatók mező, tulajdonság vagy metódus megjegyzéséhez.

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

Híváswebhely megjelölése platformspecifikusként

A platformneveknek meg kell egyeznie a hívó platformfüggetlen API-val. Ha a platform sztringje tartalmaz egy verziót:

  • Az attribútum esetében a [SupportedOSPlatform("platformVersion")] híváshelyplatformnak version nagyobbnak vagy egyenlőnek kell lennie, mint a hívóplatform Version

  • Az attribútum esetében a [UnsupportedOSPlatform("platformVersion")] híváshelyplatformnak version kisebbnek vagy egyenlőnek kell lennie a hívó 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();
    }
    

A híváshely érvényesítése platformellenőrzéssel

A platformőr példáiban használt összes feltételes ellenőrzés használható feltételként Debug.Assert(Boolean)is.

// An API supported only on Linux.
[SupportedOSPlatform("linux")]
public void LinuxOnlyApi() { }

public void Caller()
{
    Debug.Assert(OperatingSystem.IsLinux());

    LinuxOnlyApi(); // will not warn
}

Lásd még