平台相容性分析器

您可能聽過「單一 .NET」的格言:單一、統一的平臺,可用於建立任何類型的應用程式。 .net 5 SDK 包含 ASP.NET Core、Entity Framework Core、WinForms、WPF、Xamarin 和 ML .net,而且會隨著時間增加更多平臺的支援。 .NET 5 致力於提供一種體驗,讓您不必擔心不同的 .NET 種類,但也不會嘗試完全抽象化基礎作業系統) (作業系統。 您將繼續能夠呼叫平臺專屬的 Api,例如 P/Invoke、WinRT 或適用于 iOS 和 Android 的 Xamarin 系結。

但是,在元件上使用平臺特定的 Api,表示程式碼無法在所有平臺上運作。 我們需要在設計階段偵測到此情況的方法,讓開發人員在不小心使用平臺特定 Api 時取得診斷。 為了達成此目標,.NET 5 引進了 平臺相容性分析器 和互補的 api,協助開發人員在適當的情況下識別及使用平臺特定的 api。

新的 Api 包括:

  • SupportedOSPlatformAttribute 將 Api 標注為平臺特定的批註,並 UnsupportedOSPlatformAttribute 將 api 標注為在特定 OS 上不受支援。 這些屬性可以選擇性地包含版本號碼,並已套用至核心 .NET 程式庫中的某些平臺特定 Api。
  • Is<Platform>() 以及 Is<Platform>VersionAtLeast(int major, int minor = 0, int build = 0, int revision = 0) 類別中的靜態方法,可 System.OperatingSystem 安全地呼叫平臺特定的 api。 例如, OperatingSystem.IsWindows() 可以用來保護對 Windows 特定 api 的呼叫,而 OperatingSystem.IsWindowsVersionAtLeast () 可用來保護已建立版本的 Windows 特定 api 呼叫。 請參閱這些方法的 範例 ,以瞭解如何使用這些方法來作為平臺特定 API 參考的防護。

必要條件

平臺相容性分析器是 Roslyn 的程式碼品質分析器之一。 從 .NET 5 開始,這些分析器會 隨附于 .NET SDK。 根據預設,平臺相容性分析器僅針對以或更新版本為目標的專案啟用 net5.0 。 不過,您可以針對以其他架構為目標的專案 啟用它

分析器如何判斷平臺相關性

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

  • 標記為的 API [SupportedOSPlatform("platform")] 只會被視為可移植到指定的平臺和任何平臺的子集。

    • 您可以多次套用屬性,以指出 多個平臺支援(例如) [SupportedOSPlatform("windows"), SupportedOSPlatform("Android29.0")]
    • 如果平臺是 另一個平臺的子集,則屬性工作表示也支援超集合平臺。 例如, [SupportedOSPlatform("iOS")] 意指 API iOS 也在其超集合平臺上受到支援 MacCatalyst
    • 如果未使用適當的 平臺內容 參考平臺特定 api,分析器會產生 警告
      • 如果專案未以支援的平臺為目標,則會 發出警告 (例如,從以 iOS) 為目標的專案呼叫的 Windows 特定 API <TargetFramework>net5.0-ios14.0</TargetFramework>
      • 如果專案跨平臺,並呼叫平臺特定 api (例如,從跨平臺 TFM) 呼叫的 Windows 特定 api,則會 發出警告 <TargetFramework>net5.0</TargetFramework>
      • 如果在以任何 指定平臺 為目標的專案中參考平臺特定的 api,則 不會發出警告 (例如,針對以 Windows 為目標的專案所呼叫的 Windows 特定 api, <TargetFramework>net5.0-windows</TargetFramework> 並啟用專案) 的 AssemblyInfo 檔產生
      • 如果平臺專屬的 api 呼叫受到對應平臺檢查方法的保護,則 不會發出警告 (例如,由) 保護的 Windows 特定 api 呼叫 OperatingSystem.IsWindows()
      • 如果從相同平臺特定的內容參考平臺特定的 API, (呼叫網站也 以) 進行屬性化,則 不會發出警告 [SupportedOSPlatform("platform")
  • 標記為的 API 在 [UnsupportedOSPlatform("platform")] 指定的平臺和任何平臺上都被視為不受支援,但所有其他平臺皆支援此 API。

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

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

        <ItemGroup>
            <SupportedPlatform Include="platform" />
        </ItemGroup>
        
      • 如果您要建立的應用程式不是以不受支援的平臺為目標,或為多目標,且該平臺未包含在預設的 MSBuild <SupportedPlatform> items 群組中,則 不會發出警告

  • 這兩個屬性都可以使用或不含版本號碼作為平臺名稱的一部分來具現化。 版本號碼的格式 major.minor[.build[.revision]] 為; major.minor 是必要的, build 而且和 revision 部分是選擇性的。 例如,"Windows 6.1" 表示 Windows 版本6.1,但 "Windows" 會轉譯為 Windows 0.0。

如需詳細資訊,請參閱 屬性如何運作的範例,以及它們所造成的診斷

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

分析器不會檢查目標 framework 的標記 (從 MSBuild 的屬性(例如或) TFM) 目標平臺 <TargetFramework> <TargetFrameworks> 。 如果 TFM 有目標平臺,MSBuild SupportedOSPlatform 會在 AssemblyInfo .cs 檔案中插入具有目標平臺名稱的屬性,該檔案是由分析器取用。 例如,如果 TFM 為 net5.0-windows10.0.19041 ,MSBuild 會將屬性插入 [assembly: System.Runtime.Versioning.SupportedOSPlatform("windows10.0.19041")] AssemblyInfo .cs 檔案,而整個元件則視為只 Windows。 因此,呼叫以7.0 或以下版本為限 Windows 的 api 時,不會在專案中產生任何警告。

注意

如果專案的 AssemblyInfo 檔產生已停用 (也就是 <GenerateAssemblyInfo> 屬性設定為 false) ,則 MSBuild 無法新增必要的元件層級 SupportedOSPlatform 屬性。 在此情況下,即使您是以該平臺為目標,您還是可以看到平臺特定 Api 使用的警告。 若要解決這些警告,請啟用 AssemblyInfo 檔產生,或在您的專案中手動加入屬性。

平臺包含

.NET 6 引進 平臺包含 的概念,其中一個平臺可以是另一個平臺的子集。 子集平臺的注釋暗示相同的支援 (或缺少其超集合平臺) 。 如果類型中的平臺檢查方法 OperatingSystemSupportedOSPlatformGuard("supersetPlatform")] 屬性,則會被 supersetPlatform 視為該方法所檢查的作業系統平臺超集合。

例如,方法的 OperatingSystem.IsIOS() 屬性為 [SupportedOSPlatformGuard("MacCatalyst")] 。 因此,適用下列語句:

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

請考慮下列涵蓋範圍矩陣,其中✔️指出支援平臺,並 ❌ 指出 支援該平臺。

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

提示

相同的規則適用于 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() { }

屬性組合的 Advanced 案例

  • 如果有 [SupportedOSPlatform] 和屬性的組合 [UnsupportedOSPlatform] ,則所有屬性都會依作業系統平臺識別碼分組:

    • 僅支援的清單。 如果每個作業系統平臺的最低版本是 [SupportedOSPlatform] 屬性,則會將 API 視為僅受列出的平臺支援,而且所有其他平臺都不支援此 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();
      
    • 唯一不支援的清單。 如果每個作業系統平臺的最低版本是 [UnsupportedOSPlatform] 屬性,則會將 API 視為只有列出的平臺不支援,而且所有其他平臺都支援此 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 ApiSupportedFromWindows8UnsupportFromWindows10();
      
    • 不一致的清單。 如果某些平臺的最低版本是 [SupportedOSPlatform][UnsupportedOSPlatform] 其他平臺上,則會被視為不一致,分析器不支援此版本。 如果發生不一致的情況,分析器會忽略 [UnsupportedOSPlatform] 平臺。

      • 如果和屬性的最小版本 [SupportedOSPlatform] [UnsupportedOSPlatform] 相等,分析器會將平臺視為 支援的唯一清單 的一部分。
  • 平臺屬性可以套用至類型、成員 (方法、欄位、屬性和事件) 以及具有不同平臺名稱或版本的元件。

    • 在最上層套用的屬性 target 會影響其所有成員和類型。
    • 只有當子系層級的屬性符合規則「子批註可以縮小平臺支援,但無法將其加寬」時,才適用。
      • 當父系 僅支援 清單時,子成員屬性無法加入新的平臺支援,因為這樣會擴充父系支援。 只能將新平臺的支援新增至父系本身。 但是子系可以具有 Supported 與較新版本相同平臺的屬性,因為這樣會縮小支援。 此外,子系的屬性也可以是相同的平臺,也就是可 Unsupported 縮小父支援。
      • 當父系有 不支援 的清單時,子成員屬性可以新增新平臺的支援,因為這樣會縮小父系支援。 但是,它不能有與 Supported 父系相同平臺的屬性,因為它會擴充父系支援。 相同平臺的支援只能加入至套用原始屬性的父系 Unsupported
    • 如果為 [SupportedOSPlatform("platformVersion")] 相同名稱的 API 套用了一次以上 platform ,分析器只會考慮具有最小版本的應用程式。
    • 如果 [UnsupportedOSPlatform("platformVersion")] 為相同名稱的 API 套用了兩次以上 platform ,分析器就只會將這兩個版本視為最舊的版本。

    注意

    一開始支援的 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 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 6.2 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 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 標記為平臺專屬的 Api,如此一來,就能有效地將需求轉送至您的呼叫端。 使用與參考的平臺相依呼叫相同的屬性,標記包含方法或類型或整個元件。 範例

  • 使用平臺檢查判斷提示呼叫位置。 如果您不想要在執行時間額外負荷額外的 if 語句,請使用 Debug.Assert(Boolean)範例

  • 刪除程式碼。 通常不是您想要的,因為這表示當 Windows 使用者使用您的程式碼時,將會失去精確度。 如果存在跨平臺的替代方案,您可能會比使用平臺專用的 Api 更好。

  • 隱藏警告。 您也可以直接透過 EditorConfig 專案或來隱藏警告 #pragma warning disable CA1416 。 不過,此選項應該是使用平臺特定 Api 時的最後手段。

    提示

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

使用 guard 方法保護平臺特定的 Api

Guard 方法的平臺名稱應該與呼叫平臺相依的 API 平臺名稱相符。 如果呼叫 API 的平臺字串包含版本:

  • 若為 [SupportedOSPlatform("platformVersion")] 屬性,guard 方法平臺 version 應大於或等於呼叫平臺的 Version

  • 若為 [UnsupportedOSPlatform("platformVersion")] 屬性,guard 方法的平臺 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)))
        {
            ApiSupportedFromWindows8UnsupportFromWindows10();
        }
    
        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
        }
    }
    
  • 如果您需要保護以 netstandardnetcoreapp 不提供新 api 為目標的程式碼 OperatingSystem ,則 RuntimeInformation.IsOSPlatform 可以使用 API,並將會由分析器來遵守。 但是,它並不像新增的 Api 一樣優化 OperatingSystem 。 如果結構中不支援該平臺 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 。 不過,您可能會想要在欄位中快取 guard 結果並重複使用,或使用自訂防護方法來檢查平臺。 分析器需要將這類 Api 辨識為自訂防護,而且不應該對它們所保護的 Api 發出警告。 在 .NET 6 中引進的 guard 屬性可支援此案例:

這些屬性可以選擇性地包含版本號碼。 您可以多次套用這些應用程式,以保護一個以上的平臺,並可用於批註欄位、屬性或方法。

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 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("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. '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' 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. '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("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.
        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 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
}

另請參閱