Penganalisis kompatibilitas platform

Anda mungkin telah mendengar motto "One .NET": satu platform terpadu untuk membangun semua jenis aplikasi. .NET 5 SDK mencakup ASP.NET Core, Entity Framework Core, WinForms, WPF, Xamarin, dan ML.NET, dan akan menambahkan dukungan untuk lebih banyak platform dari waktu ke waktu. .NET 5 berusaha untuk memberikan pengalaman di mana Anda tidak perlu beralasan tentang berbagai rasa .NET, tetapi tidak mencoba untuk sepenuhnya mengabstraksi sistem operasi (OS) yang mendasarinya. Anda akan terus dapat memanggil API khusus platform, misalnya, P/Invokes, WinRT, atau pengikatan Xamarin untuk iOS dan Android.

Tetapi menggunakan API khusus platform pada komponen berarti kode tidak lagi berfungsi di semua platform. Kami memerlukan cara untuk mendeteksi ini pada waktu desain sehingga pengembang mendapatkan diagnostik ketika mereka secara tidak sengaja menggunakan API khusus platform. Untuk mencapai tujuan ini, .NET 5 memperkenalkan penganalisis kompatibilitas platform dan API pelengkap untuk membantu pengembang mengidentifikasi dan menggunakan API khusus platform jika sesuai.

API baru meliputi:

  • SupportedOSPlatformAttribute untuk membuat anotasi API sebagai khusus platform dan UnsupportedOSPlatformAttribute untuk membuat anotasi API sebagai tidak didukung pada OS tertentu. Atribut ini dapat secara opsional menyertakan nomor versi, dan telah diterapkan ke beberapa API khusus platform di pustaka .NET inti.
  • Is<Platform>() dan Is<Platform>VersionAtLeast(int major, int minor = 0, int build = 0, int revision = 0) metode statis di System.OperatingSystem kelas untuk memanggil API khusus platform dengan aman. Misalnya, OperatingSystem.IsWindows() dapat digunakan untuk melindungi panggilan ke API khusus Windows, dan OperatingSystem.IsWindowsVersionAtLeast() dapat digunakan untuk melindungi panggilan API khusus Windows versi. Lihat contoh-contoh dari cara metode ini dapat digunakan sebagai pelindung referensi API khusus platform.

Prasyarat

Penganalisis kompatibilitas platform adalah salah satu penganalisis kualitas kode Roslyn. Mulai Visual Studio 5 dan .NET 5.0, penganalisis ini disertakan dengan .NET SDK. Penganalisis kompatibilitas platform diaktifkan secara default hanya untuk proyek yang menargetkan net5.0 atau versi yang lebih baru. Namun, Anda dapat mengaktifkannya untuk proyek yang menargetkan kerangka kerja lain.

Bagaimana penganalisis menentukan dependensi platform

  • API yang tidak ditangguhkan dianggap berfungsi di semua platform OS.

  • API yang ditandai dengan [SupportedOSPlatform("platform")] dianggap hanya portabel ke platform yang ditentukan dan platform apa pun yang merupakan subsetnya.

    • Atribut dapat diterapkan beberapa kali untuk menunjukkan beberapa dukungan platform, misalnya [SupportedOSPlatform("windows"), SupportedOSPlatform("Android29.0")].
    • Jika platform adalah bagian dari platform lain, atribut tersebut menyiratkan bahwa platform tersebut juga didukung. Misalnya, [SupportedOSPlatform("iOS")] menyiratkan bahwa API didukung pada iOS dan juga pada platform superset-nya, MacCatalyst.
    • Penganalisis akan menghasilkan peringatan jika API khusus platform dirujuk tanpa konteks platform yang tepat:
      • Memperingatkan jika proyek tidak menargetkan platform yang didukung (misalnya, API khusus Windows yang dipanggil dari proyek yang menargetkan iOS <TargetFramework>net5.0-ios14.0</TargetFramework>).
      • Memperingatkan apakah proyek tersebut lintas platform dan memanggil API khusus platform (misalnya, API khusus Windows yang dipanggil dari TFM <TargetFramework>net5.0</TargetFramework>lintas platform ).
      • Tidak memperingatkan apakah API khusus platform dirujuk dalam proyek yang menargetkan salah satu platform yang ditentukan (misalnya, untuk API khusus Windows yang disebut dari jendela penargetan proyek <TargetFramework>net5.0-windows</TargetFramework> dan pembuatan file AssemblyInfo.cs diaktifkan untuk proyek).
      • Tidak memperingatkan apakah panggilan API khusus platform dilindungi oleh metode pemeriksaan platform yang sesuai (misalnya, panggilan API khusus Windows yang dijaga oleh OperatingSystem.IsWindows()).
      • Tidak memperingatkan apakah API khusus platform dirujuk dari konteks khusus platform yang sama (situs panggilan juga diatribusikan dengan [SupportedOSPlatform("platform")).
  • API yang ditandai dengan [UnsupportedOSPlatform("platform")] dianggap tidak didukung pada platform yang ditentukan dan platform apa pun yang merupakan subsetnya, tetapi didukung untuk semua platform lainnya.

    • Atribut dapat diterapkan beberapa kali dengan platform yang berbeda, misalnya, [UnsupportedOSPlatform("iOS"), UnsupportedOSPlatform("Android29.0")].
    • Jika platform adalah bagian dari platform lain, atribut tersebut menyiratkan bahwa platform tersebut juga didukung. Misalnya, [UnsupportedOSPlatform("iOS")] menyiratkan bahwa API didukung pada iOS dan juga pada platform superset-nya, MacCatalyst.
    • Penganalisis menghasilkan peringatan hanya jika platform efektif untuk situs panggilan:
      • Memperingatkan jika proyek menargetkan platform yang diatribusikan sebagai tidak didukung (misalnya, jika API dikaitkan dengan [UnsupportedOSPlatform("windows")] dan situs panggilan menargetkan <TargetFramework>net5.0-windows</TargetFramework>).

      • Memperingatkan jika proyek multi-target dan platform disertakan dalam grup item MSBuild <SupportedPlatform> default, atau platform disertakan secara manual dalam MSBuild<grup item SupportedPlatform> :

        <ItemGroup>
            <SupportedPlatform Include="platform" />
        </ItemGroup>
        
      • Tidak memperingatkan jika Anda membangun aplikasi yang tidak menargetkan platform yang tidak didukung atau multi-target dan platform tidak disertakan dalam grup item MSBuild <SupportedPlatform> default.

  • Kedua atribut dapat dipakai dengan atau tanpa nomor versi sebagai bagian dari nama platform. Nomor versi dalam format major.minor[.build[.revision]]; major.minor diperlukan dan build bagian dan revision bersifat opsional. Misalnya, "Windows6.1" menunjukkan Windows versi 6.1, tetapi "Windows" ditafsirkan sebagai Windows 0.0.

Untuk informasi selengkapnya, lihat contoh cara kerja atribut dan diagnostik apa yang mereka sebabkan.

Bagaimana penganalisis mengenali platform target TFM

Penganalisis tidak memeriksa target kerangka kerja moniker (TFM) platform target dari properti MSBuild, seperti <TargetFramework> atau <TargetFrameworks>. Jika TFM memiliki platform target, MS Build menyuntikkan atribut SupportedOSPlatform dengan nama platform yang ditargetkan dalam file AssemblyInfo.cs, yang digunakan oleh penganalisis. Misalnya, jika TFM adalah net5.0-windows10.0.19041, MSBuild memasukkan [assembly: System.Runtime.Versioning.SupportedOSPlatform("windows10.0.19041")] atribut ke dalam file AssemblyInfo.cs, dan seluruh assembly dianggap hanya untuk Windows. Oleh karena itu, memanggil API khusus Windows dengan versi 7.0 atau di bawahnya tidak akan menyebabkan peringatan apa pun dalam proyek.

Catatan

Jika pembuatan file AssemblyInfo.cs dinonaktifkan untuk proyek (yaitu, properti <GenerateAssemblyInfo> diatur ke false), atribut SupportedOSPlatform tingkat rakitan yang diperlukan tidak dapat ditambahkan oleh SDK. Dalam hal ini, Anda dapat melihat peringatan untuk penggunaan API khusus platform meskipun Anda menargetkan platform tersebut. Untuk mengatasi peringatan, aktifkan pembuatan file AssemblyInfo.cs atau tambahkan atribut secara manual di proyek Anda.

Penyertaan platform

.NET 6 memperkenalkan konsep penyertaan platform, di mana satu platform dapat menjadi subset dari platform lain. Anotasi untuk platform subset menyiratkan dukungan yang sama (atau kurangnya) untuk platform superset. Jika metode pemeriksaan platform dalam OperatingSystem jenis memiliki SupportedOSPlatformGuard("supersetPlatform")] atribut, maka supersetPlatform dianggap sebagai superset platform OS yang diperiksa metodenya.

Misalnya, OperatingSystem.IsIOS() metode diatribusikan [SupportedOSPlatformGuard("MacCatalyst")]. Oleh karena itu, pernyataan berikut berlaku:

  • Metode OperatingSystem.IsIOS() dan OperatingSystem.IsIOSVersionAtLeast memeriksa tidak hanya iOS platform, tetapi juga MacCatalyst platform.
  • Misalnya, [SupportedOSPlatform("iOS")] menyiratkan bahwa API didukung pada iOS dan juga pada platform superset-nya, MacCatalyst. Anda dapat menggunakan [UnsupportedOSPlatform("MacCatalyst")] atribut untuk mengecualikan dukungan tersirat ini.
  • [UnsupportedOSPlatform("iOS") menyiratkan bahwa API tidak didukung pada iOS dan MacCatalyst. Anda dapat menggunakan [SupportedOSPlatform("MacCatalyst")] atribut untuk mengecualikan dukungan tersirat ini.

Pertimbangkan matriks cakupan berikut, di mana ✔️ menunjukkan bahwa platform didukung, dan ❌ menunjukkan bahwa platform tidak didukung.

Platform SupportedOSPlatform(subset) SupportedOSPlatform(superset) UnsupportedOSPlatform(subset) UnsupportedOSPlatform(superset)
Subset ✔️ ✔️
Superset ✔️ ✔️ ✔️ ✔️

Tip

Aturan yang sama berlaku untuk SupportedOSPlatformGuard dan UnsupportedOSPlatformGuard atribut.

Cuplikan kode berikut menunjukkan bagaimana Anda dapat menggabungkan atribut untuk mengatur tingkat dukungan yang tepat.

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

Skenario tingkat lanjut untuk kombinasi atribut

  • Jika kombinasi atribut [SupportedOSPlatform] dan [UnsupportedOSPlatform] ada, semua atribut dikelompokkan menurut pengidentifikasi platform OS:

    • Daftar yang didukung saja. Jika versi terendah untuk setiap platform OS adalah atribut [SupportedOSPlatform], API dianggap hanya didukung oleh platform yang terdaftar dan tidak didukung oleh semua platform lainnya. Atribut opsional [UnsupportedOSPlatform] untuk setiap platform hanya dapat memiliki versi yang lebih tinggi dari versi minimum yang didukung, yang menunjukkan bahwa API dihapus mulai dari versi yang ditentukan.

      // 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();
      
    • Daftar yang didukung saja. Jika versi terendah untuk setiap platform OS adalah atribut [UnsupportedOSPlatform], maka API dianggap hanya tidak didukung oleh platform yang terdaftar dan didukung oleh semua platform lainnya. Daftar tersebut dapat memiliki [SupportedOSPlatform] atribut dengan platform yang sama, tetapi hanya dengan versi yang lebih tinggi, yang menunjukkan bahwa API didukung sejak versi tersebut.

      // 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();
      
    • Daftar yang tidak konsisten. Jika versi terendah untuk beberapa platform adalah [SupportedOSPlatform] sementara [UnsupportedOSPlatform] untuk platform lain, itu dianggap tidak konsisten, yang tidak didukung untuk penganalisis. Jika inkonsistensi terjadi, penganalisis [UnsupportedOSPlatform] mengabaikan platform.

      • Jika versi [SupportedOSPlatform] dan [UnsupportedOSPlatform] atribut terendah adalah sama, penganalisis menganggap platform sebagai bagian dari daftar Hanya didukung.
  • Atribut platform dapat diterapkan ke jenis, anggota (metode, bidang, properti, dan peristiwa) dan assembly dengan nama atau versi platform yang berbeda.

    • Atribut yang diterapkan di tingkat target atas memengaruhi semua anggota dan jenisnya.
    • Atribut tingkat anak hanya berlaku jika mematuhi aturan "anotasi anak dapat mempersempit dukungan platform, tetapi tidak dapat memperlebarnya".
      • Ketika induk memiliki daftar Hanya didukung, atribut anggota anak tidak dapat menambahkan dukungan platform baru, karena itu akan memperluas dukungan induk. Dukungan untuk platform baru hanya dapat ditambahkan ke induk itu sendiri. Tetapi anak dapat memiliki Supported atribut untuk platform yang sama dengan versi yang lebih baru karena mempersempit dukungan. Selain itu, anak dapat memiliki Unsupported atribut dengan platform yang sama seperti yang juga mempersempit dukungan induk.
      • Ketika induk hanya memiliki daftar yang tidak didukung, atribut anggota anak dapat menambahkan dukungan untuk platform baru, karena mempersempit dukungan induk. Tetapi tidak dapat memiliki Supported atribut untuk platform yang sama dengan induk, karena itu memperluas dukungan induk. Dukungan untuk platform yang sama hanya dapat ditambahkan ke induk tempat atribut asli Unsupported diterapkan.
    • Jika [SupportedOSPlatform("platformVersion")] diterapkan lebih dari sekali untuk API dengan nama yang sama platform, penganalisis hanya mempertimbangkan satu dengan versi minimum.
    • Jika [UnsupportedOSPlatform("platformVersion")] diterapkan lebih dari sekali untuk API dengan nama yang sama platform, penganalisis hanya mempertimbangkan keduanya dengan versi minimum.

    Catatan

    API yang awalnya didukung tetapi tidak didukung (dihapus) dalam versi yang lebih baru diharapkan tidak didukung kembali dalam versi yang bahkan lebih baru.

Contoh cara kerja atribut dan diagnostik apa yang dihasilkannya

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

Menangani peringatan yang dilaporkan

Cara yang disarankan untuk menangani diagnostik ini adalah memastikan Anda hanya memanggil API khusus platform saat berjalan di platform yang sesuai. Berikut ini adalah opsi yang dapat Anda gunakan untuk mengatasi peringatan; pilih mana yang paling tepat untuk situasi Anda:

  • Lindungi panggilan. Anda dapat mencapainya dengan memanggil kode secara kondisional pada durasi. Periksa apakah Anda menjalankan pada yang diinginkan Platform dengan menggunakan salah satu metode pemeriksaan platform, misalnya, OperatingSystem.Is<Platform>() atau OperatingSystem.Is<Platform>VersionAtLeast(int major, int minor = 0, int build = 0, int revision = 0). Contoh.

  • Tandai situs panggilan sebagai khusus platform. Anda dapat memilih untuk menandai API Anda sendiri sebagai khusus platform, yang secara efektif meneruskan persyaratan ke pemanggil Anda. Tandai metode atau jenis yang berisi atau seluruh assembly dengan atribut yang sama dengan panggilan yang bergantung pada platform yang dirujuk. Contoh.

  • Tegaskan situs panggilan dengan pemeriksaan platform. Jika Anda tidak ingin overhead pernyataan tambahan if pada durasi, gunakan Debug.Assert(Boolean). Contoh.

  • Hapus kode. Umumnya bukan apa yang Anda inginkan karena itu berarti Anda kehilangan keakuratan ketika kode Anda digunakan oleh pengguna Windows. Untuk kasus di mana alternatif lintas platform ada, Anda mungkin lebih baik menggunakannya melalui API khusus platform.

  • Tekan peringatan. Anda juga dapat menekan peringatan, baik melalui entri EditorConfig atau #pragma warning disable CA1416. Namun, opsi ini harus menjadi upaya terakhir saat menggunakan API khusus platform.

    Tip

    Saat menonaktifkan peringatan menggunakan #pragma arahan pra-pengkompilasi, pengidentifikasi yang Anda targetkan peka huruf besar/kecil. Misalnya, ca1416 tidak akan benar-benar menonaktifkan peringatan CA1416.

Melindungi API khusus platform dengan metode penjaga

Nama platform metode pelindung harus cocok dengan nama platform API yang bergantung pada platform panggilan. Jika string platform API panggilan menyertakan versi:

  • [SupportedOSPlatform("platformVersion")] Untuk atribut, platform version metode pelindung harus lebih besar dari atau sama dengan platform Versionpanggilan.

  • Untuk [UnsupportedOSPlatform("platformVersion")] atribut, platform version metode pelindung harus lebih besar dari atau sama dengan platform Versionpanggilan.

    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
        }
    }
    
  • Jika Anda perlu melindungi kode yang menargetkan atau netstandard di mana API baru netcoreapp tidak tersedia, OperatingSystem API dapat digunakan dan akan dihormati oleh penganalisisRuntimeInformation.IsOSPlatform. Tetapi tidak dioptimalkan seperti API baru yang ditambahkan di OperatingSystem. Jika platform tidak didukung dalam OSPlatform struct, Anda dapat memanggil OSPlatform.Create(String) dan meneruskan nama platform, yang juga dihormati oleh penganalisis.

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

Membuat anotasi API dengan atribut penjaga platform dan menggunakannya sebagai penjaga kustom

Seperti yang ditunjukkan sebelumnya, penganalisis mengenali metode statis pelindung platform dalam OperatingSystem jenis, seperti OperatingSystem.IsWindows, dan juga RuntimeInformation.IsOSPlatform. Namun, Anda mungkin ingin menyimpan hasil pelindung di bidang dan menggunakannya kembali, atau menggunakan metode penjaga kustom untuk memeriksa platform. Penganalisis perlu mengenali API tersebut sebagai pelindung kustom dan tidak boleh memperingatkan API yang dilindungi oleh mereka. Atribut pelindung diperkenalkan di .NET 6 untuk mendukung skenario ini:

  • SupportedOSPlatformGuardAttribute membuat anotasi API yang dapat digunakan sebagai pelindung untuk API yang dianotasi dengan SupportedOSPlatformAttribute.
  • UnsupportedOSPlatformGuardAttribute membuat anotasi API yang dapat digunakan sebagai pelindung untuk API yang dianotasi dengan UnsupportedOSPlatformAttribute.

Atribut ini dapat secara opsional menyertakan nomor versi. Mereka dapat diterapkan beberapa kali untuk melindungi lebih dari satu platform dan dapat digunakan untuk membuat anotasi bidang, properti, atau metode.

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

Tandai situs panggilan sebagai khusus platform

Nama platform harus cocok dengan API yang bergantung pada platform panggilan. Jika string platform menyertakan versi:

  • Untuk [SupportedOSPlatform("platformVersion")] atribut, platform situs panggil version harus lebih besar dari atau sama dengan platform Versionpanggilan

  • Untuk [UnsupportedOSPlatform("platformVersion")] atribut, platform situs panggil version harus lebih kecil dari atau sama dengan platform Versionpanggilan

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

Tegaskan situs panggilan dengan pemeriksaan platform

Semua pemeriksaan kondisional yang digunakan dalam contoh pelindung platform juga dapat digunakan sebagai kondisi untuk 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
}

Lihat juga