平台相容性分析器
「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 包括:
- SupportedOSPlatformAttribute 可將 API 標註為平台專屬,且 UnsupportedOSPlatformAttribute可將 API 標註為在特定 OS 上不受支援。 這些屬性可以選擇性包含版本號碼,並已套用至核心 .NET 程式庫中的某些平台專屬 API。
- System.OperatingSystem 類別中的
Is<Platform>()
和Is<Platform>VersionAtLeast(int major, int minor = 0, int build = 0, int revision = 0)
靜態方法,用於安全呼叫平台專屬 API。 例如,OperatingSystem.IsWindows() 可用來保護對 Windows 專屬 API 的呼叫,而 OperatingSystem.IsWindowsVersionAtLeast() 可用來保護已設定版本的 Windows 專屬 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")
加以歸屬),則不警告。
- 如果專案不是以受支援的平台為目標 (例如,從以 iOS
- 此屬性可以多次套用,以表示多平台支援,例如
標示為
[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
為必要,而build
和revision
組件則為選擇性。 例如 "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")
表示iOS
和MacCatalyst
不支援 API。 您可以使用[SupportedOSPlatform("MacCatalyst")]
屬性來排除這種隱含的缺乏支援。
請考量下列涵蓋範圍矩陣,其中 ✔️ 表示平台受支援,而 ❌ 則表示平台不受支援。
平台 | SupportedOSPlatform(subset) |
SupportedOSPlatform(superset) |
UnsupportedOSPlatform(subset) |
UnsupportedOSPlatform(superset) |
---|---|---|---|---|
子集 | ✔️ | ❌ | ✔️ | ❌ |
超集 | ✔️ | ✔️ | ✔️ | ✔️ |
提示
相同的規則適用於 SupportedOSPlatformGuard
和 UnsupportedOSPlatformGuard
屬性。
下列程式碼片段示範如何結合屬性來設定正確的支援層級。
// 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 的
netstandard
或netcoreapp
做為目標的程式碼,則可使用 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.IsWindows
和 RuntimeInformation.IsOSPlatform。 不過可能需要將防護結果在欄位中快取處理,並重複使用,或使用自訂防護方法來檢查平台。 分析器需要將這類 API 辨識為自訂防護,且不應對受其保護的 API 發出警告。 在 .NET 6 中引進了防護屬性以支援此案例:
SupportedOSPlatformGuardAttribute
標註 API,這類 API 可用來做為以 SupportedOSPlatformAttribute 標註之 API 的防護。UnsupportedOSPlatformGuardAttribute
標註 API,這類 API 可用來做為以 UnsupportedOSPlatformAttribute 標註之 API 的防護。
這些屬性可以選擇性包含版本號碼, 可多次套用來保護多個平台,並可用於標註欄位、屬性或方法。
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
}