平台相容性分析器

「One .NET」的口號可能常常聽到: 以單一整合平台便能建置任何類型的應用程式。 .NET 5 SDK 包括 ASP.NET Core、Entity Framework Core、WinForms、WPF、Xamarin 和 ML.NET,且會隨著時間新增更多平台的支援。 .NET 5 致力提供一種體驗,讓使用者不必判斷不同的 .NET 類別,但並不嘗試將基礎作業系統 (OS) 完全抽象化。 而是需繼續呼叫平台專屬的 API,例如 P/Invokes、WinRT 或是 iOS 和 Android 的 Xamarin 繫結。

但是,在元件上使用平台專屬的 API,即代表程式碼不再跨所有平台運作。 需要有辦法在設計階段偵測此狀況,讓開發人員能在意外使用平台專屬 API 時取得診斷資訊。 為了達成此目標,.NET 5 引進了 平台相容性分析器 和補充 API,以協助開發人員適當地識別和使用平台專屬 API。

新的 API 包括:

必要條件

平台相容性分析器是其中一種 Roslyn 程式碼品質分析器。 從 .NET 5.0 開始,這些分析器即 隨附於 .NET SDK。 依預設,平台相容性分析器只會針對以 net5.0 或後續版本為目標的專案啟用。 不過對於以其他架構為目標的專案,也能啟用分析器

分析器如何判斷平台相依性

  • 未歸屬的 API 會視為可在所有 OS 平台上運作。

  • 標示為 [SupportedOSPlatform("platform")] 的 API 只會視為可移植到指定平台以及任何其屬於子集的平台。

    • 此屬性可以多次套用,以表示多平台支援,例如 [SupportedOSPlatform("windows"), SupportedOSPlatform("Android29.0")]
    • 如果平台是另一個平台的子集,則此屬性表示也支援超集的平台。 例如,[SupportedOSPlatform("iOS")] 表示 API 在 iOS 上以及其超集平台 MacCatalyst 上受支援。
    • 如果沒有適當的平台內容而參考了平台專屬 API,分析器將會產生警告
      • 如果專案不是以受支援的平台為目標 (例如,從以 iOS <TargetFramework>net5.0-ios14.0</TargetFramework> 為目標的專案呼叫的 Windows 特定 API),則會發出警告
      • 如果是跨平台專案且會呼叫平台專屬 API (例如,從跨平台 TFM <TargetFramework>net5.0</TargetFramework> 呼叫的 Windows 特定 API),則會發出警告
      • 如果是在以任何指定平台為目標的專案內參考平台專屬 API (例如,針對從以 Windows <TargetFramework>net5.0-windows</TargetFramework> 為目標的專案呼叫的 Windows 專屬 API,且會對該專案啟用 AssemblyInfo.cs 檔案產生作業),則不警告
      • 如果平台專屬 API 呼叫受到對應的平台檢查方法所防護 (例如,受 OperatingSystem.IsWindows() 防護的 Windows 專屬 API 呼叫),則不警告
      • 如果從相同的平台專屬內容參考平台專屬 API (呼叫位置也以 [SupportedOSPlatform("platform") 加以歸屬),則不警告
  • 標示為 [UnsupportedOSPlatform("platform")] API 會視為在指定平台以及任何其屬於子集的平台上不受支援,但在所有其他平台都受支援。

    • 不同的平台可以套用此屬性多次,例如 [UnsupportedOSPlatform("iOS"), UnsupportedOSPlatform("Android29.0")]
    • 如果平台是另一個平台的子集,則此屬性表示超集平台也不受支援。 例如,[UnsupportedOSPlatform("iOS")] 表示 API 在 iOS 上以及其超集平台 MacCatalyst 上不受支援。
    • 只有當 platform 對呼叫位置有效時,分析器才會產生警告
      • 如果專案的目標是歸屬為不受支援的平台 (例如若 API 是以 [UnsupportedOSPlatform("windows")] 加以歸屬,且呼叫位置以 <TargetFramework>net5.0-windows</TargetFramework> 為目標),則發出警告

      • 如果專案是多目標專案,且 platform 包含在預設 MSBuild <SupportedPlatform> 項目群組中,或是 platform 手動包含在 MSBuild<SupportedPlatform> 項目群組內,則發出警告

        <ItemGroup>
            <SupportedPlatform Include="platform" />
        </ItemGroup>
        
      • 如果要建置的應用程式並非以不受支援的平台為目標,或是為多目標的應用程式,且平台未包含在預設 MSBuild <SupportedPlatform> 項目群組中,則不警告

  • 無論版本號碼是否為平台名稱的一部份,這兩個屬性都可以具現化。 版本號碼的格式為 major.minor[.build[.revision]]major.minor 為必要,而 buildrevision 組件則為選擇性。 例如 "Windows6.1" 表示 Windows 6.1 版,但 "Windows" 會解譯為 Windows 0.0。

如需詳細資訊,請參閱屬性運作方式以及所產生診斷資訊的範例

分析器如何辨識 TFM 目標平台

分析器不會從 MSBuild 屬性檢查目標 Framework Moniker (TFM) 目標平台,例如 <TargetFramework><TargetFrameworks>。 如果 TFM 有目標平台,MSBuild 會在 AssemblyInfo.cs 檔案 (由此分析器取用) 中插入具有目標平台名稱的 SupportedOSPlatform 屬性。 例如,如果 TFM 為 net5.0-windows10.0.19041,MSBuild 會將 [assembly: System.Runtime.Versioning.SupportedOSPlatform("windows10.0.19041")] 屬性插入 AssemblyInfo.cs 檔案中,而且整個組件會視為僅限 Windows。 因此,呼叫設定為 7.0 或以下版本的僅限 Windows 的 API,並不會在專案中造成任何警告。

注意

如果停用了專案的 AssemblyInfo.cs 檔案產生作業 (即屬性 <GenerateAssemblyInfo> 設定為 false),MSBuild 就無法新增必要的組件層級 SupportedOSPlatform 屬性。 在此情況下,即使是以該平台為目標,仍會看到平台專屬 API 使用方式的警告。 若要解決警告,請啟用 AssemblyInfo.cs 檔案產生作業,或在專案中手動新增屬性。

平台包含

.NET 6 引進了「平台包含」 的概念,其中一個平台可以是另一個平台的子集。 子集平台的註釋會顯示對超集平台有相同支援 (或缺乏其支援)。 如果 OperatingSystem 型別中的平台檢查方法具有 SupportedOSPlatformGuard("supersetPlatform")] 屬性,則 supersetPlatform 會視為該方法所要檢查的 OS 平台超集。

例如,OperatingSystem.IsIOS() 方法已歸屬到 [SupportedOSPlatformGuard("MacCatalyst")]。 因此適用下列陳述式:

  • OperatingSystem.IsIOS()OperatingSystem.IsIOSVersionAtLeast 方法不僅會檢查 iOS 平台,也會檢查 MacCatalyst 平台。
  • [SupportedOSPlatform("iOS")] 表示 API 在 iOS 上以及其超集平台 MacCatalyst 上受支援。 您可以使用 [UnsupportedOSPlatform("MacCatalyst")] 屬性來排除此隱含的支援。
  • [UnsupportedOSPlatform("iOS") 表示 iOSMacCatalyst 不支援 API。 您可以使用 [SupportedOSPlatform("MacCatalyst")] 屬性來排除這種隱含的缺乏支援。

請考量下列涵蓋範圍矩陣,其中 ✔️ 表示平台受支援,而 ❌ 則表示平台不受支援。

平台 SupportedOSPlatform(subset) SupportedOSPlatform(superset) UnsupportedOSPlatform(subset) UnsupportedOSPlatform(superset)
子集 ✔️ ✔️
超集 ✔️ ✔️ ✔️ ✔️

提示

相同的規則適用於 SupportedOSPlatformGuardUnsupportedOSPlatformGuard 屬性。

下列程式碼片段示範如何結合屬性來設定正確的支援層級。

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

屬性組合的進階案例

  • 如果有 [SupportedOSPlatform][UnsupportedOSPlatform] 屬性的組合存在,所有屬性都會依 OS 平台識別碼分組:

    • 僅受支援清單。 如果每個 OS 平台的最低版本是 [SupportedOSPlatform] 屬性,則 API 會視為只受列出的平台支援,而在所有其他平台上不受支援。 每個平台的選擇性 [UnsupportedOSPlatform] 屬性只能有最低受支援版本的更高版本,這表示會從指定的版本開始移除 API。

      // 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();
      
    • 僅不受支援清單。 如果每個 OS 平台的最低版本是 [UnsupportedOSPlatform] 屬性,則 API 會視為只在列出的平台上不受支援,而受所有其他平台支援。 此清單可能具有平台相同、但版本較高的 [SupportedOSPlatform] 屬性,這表示從該版本開始支援 API。

      // 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();
      
    • 不一致清單。 如果某些平台的最低版本是 [SupportedOSPlatform],而其他平台的最低版本是 [UnsupportedOSPlatform],則會視為不一致,而分析器並不支援此情況。 如果發生不一致的情況,分析器會忽略 [UnsupportedOSPlatform] 平台。

      • 如果 [SupportedOSPlatform][UnsupportedOSPlatform] 屬性的最低版本相等,分析器會將該平台視為屬於僅受支援清單
  • 平台屬性可以套用至具有不同平台名稱或版本的類型、成員 (方法、欄位、屬性和事件) 和組件。

    • 在最上層 target 套用的屬性會影響其所有成員和類型。
    • 子層級屬性僅在遵守規則「子註釋可縮小平台支援範圍,但無法擴大範圍」的情況下才適用。
      • 當父系具有僅受支援清單時,子成員屬性就無法新增新的平台支援,因為這會擴大父系支援範圍。 新平台的支援只能新增至父代本身。 但子系可以有後續版本相同平台的 Supported 屬性,因為這樣會縮小支援範圍。 此外,子系也可以有具有相同平台的 Unsupported 屬性,因為這樣也會縮小父系支援範圍。
      • 當父系具有僅不受支援清單時,子成員屬性可以新增對新平台的支援,因為這樣會縮小父系支援範圍。 但是不能具有與父系相同平台的 Supported 屬性,因為這會擴大父系支援範圍。 範圍對相同平台的支援只能新增至其中已套用原始 Unsupported 屬性的父系。
    • 如果針對具有相同 platform 名稱的 API 套用 [SupportedOSPlatform("platformVersion")] 一次以上,分析器只會考慮具有最低版本的 API。
    • 如果針對具有相同 platform 名稱的 API 套用 [UnsupportedOSPlatform("platformVersion")] 兩次以上,分析器只會考慮具有最早版本的兩個 API。

    注意

    一開始受支援但在較新版本中不受支援 (已移除) 的 API,不會預期在後續版本中再受到支援。

屬性運作方式以及所產生診斷資訊的範例

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

處理回報的警告

處理這些診斷的建議方式是,確定只有在合適的平台上執行時才呼叫平台專屬 API。 以下是可用來解決警告的選項;請選擇最符合的情況:

  • 保護呼叫。 您可以在執行階段有條件地呼叫程式碼來達成此目的。 請使用其中一種平台檢查方法來檢查是否在所需的 Platform 上執行,例如 OperatingSystem.Is<Platform>()OperatingSystem.Is<Platform>VersionAtLeast(int major, int minor = 0, int build = 0, int revision = 0)範例

  • 將呼叫位置標示為平台專屬。 也可以選擇將自己的 API 標示為平台專屬,進而有效地將需求轉送到呼叫端。 可使用與參考的平台相依呼叫相同的屬性,標記包含的方法或型別,或是整個組件。 範例

  • 使用平台檢查來判斷提示呼叫位置。 如果不想在執行階段有額外 if 陳述式的負荷,請使用 Debug.Assert(Boolean)範例

  • 刪除程式碼。 通常不是您所想要的內容,因為這表示當 Windows 使用者使用您的程式碼時,您會失去精確度。 在跨平台替代方法存在的情況下,可能最好透過平台專屬 API 使用該替代方法。

  • 隱藏警告。 也可以透過 EditorConfig 項目或 #pragma warning disable CA1416,直接隱藏警告。 不過,使用平台專屬的 API 時,請將這個選項當做最後手段。

    提示

    使用 #pragma 預編譯器指示詞停用警告時,目標識別碼需區分大小寫。 例如,ca1416 不會實際停用警告 CA1416。

使用防護方法保護平台專屬 API

防護方法的平台名稱應該與呼叫方平台相依 API 平台名稱相符。 如果呼叫方 API 的平台字串包括版本:

  • 針對 [SupportedOSPlatform("platformVersion")] 屬性,防護方法平台 version 應大於或等於呼叫方平台 Version

  • 針對 [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(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
        }
    }
    
  • 如果需要保護無法使用新 OperatingSystem API 的 netstandardnetcoreapp 做為目標的程式碼,則可使用 RuntimeInformation.IsOSPlatform API,而且分析器會採用此 API。 但是這並不如 OperatingSystem 中新增的新 API 理想。 如果平台在 OSPlatform 結構中不受支援,可以呼叫 OSPlatform.Create(String) 並傳入分析器也採用的平台名稱。

    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,並將其做為自訂防護使用

如先前所示,分析器會辨識 OperatingSystem 型別中的平台防護靜態方法,例如 OperatingSystem.IsWindowsRuntimeInformation.IsOSPlatform。 不過可能需要將防護結果在欄位中快取處理,並重複使用,或使用自訂防護方法來檢查平台。 分析器需要將這類 API 辨識為自訂防護,且不應對受其保護的 API 發出警告。 在 .NET 6 中引進了防護屬性以支援此案例:

這些屬性可以選擇性包含版本號碼, 可多次套用來保護多個平台,並可用於標註欄位、屬性或方法。

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

將呼叫位置標示為平台專屬

平台名稱應該符合呼叫方的平台相依 API。 如果平台字串包括版本:

  • 針對 [SupportedOSPlatform("platformVersion")] 屬性,呼叫位置平台 version 應大於或等於呼叫方平台的 Version

  • 針對 [UnsupportedOSPlatform("platformVersion")] 屬性,呼叫位置平台 version 應小於或等於呼叫方平台的 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();
    }
    

使用平台檢查來判斷提示呼叫位置

平台防護範例中使用的所有條件式檢查也可以做為 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
}

另請參閱