CA1416: Ověření kompatibility platformy
Vlastnost | Hodnota |
---|---|
ID pravidla | CA1416 |
Název | Ověřit kompatibilitu platformy |
Kategorie | Vzájemná funkční spolupráce |
Oprava způsobující chybu nebo chybu způsobující chybu | Nenarušující |
Povoleno ve výchozím nastavení v .NET 9 | Jako upozornění |
Příčina
Porušení se hlásí, pokud se rozhraní API specifické pro platformu používá v kontextu jiné platformy nebo pokud není ověřená (platforma neutrální). Porušení se hlásí také v případě, že se používá rozhraní API, které není podporováno pro cílovou platformu projektu.
Toto pravidlo je ve výchozím nastavení povolené jenom pro projekty, které cílí na .NET 5 nebo novější. Můžete ho ale povolit pro projekty, které cílí na jiné architektury.
Popis pravidla
Rozhraní .NET 5 přidalo nové atributy SupportedOSPlatformAttribute a UnsupportedOSPlatformAttributepro přidávání poznámek rozhraní API specifických pro platformu. V rámci názvu platformy je možné vytvořit instanci obou atributů s čísly verzí nebo bez. Lze je také použít vícekrát s různými platformami.
- Neoznačené rozhraní API se považuje za funkční na všech platformách operačního systému (OS).
- Rozhraní API označené
[SupportedOSPlatform("platformName")]
jako přenosné pouze na určené platformy operačního systému. Pokud je platforma podmnožinou jiné platformy, atribut znamená, že se tato platforma podporuje také. - Rozhraní API označené
[UnsupportedOSPlatform("platformName")]
jako nepodporované na zadaných platformách operačního systému se považuje za nepodporované. Pokud je platforma podmnožinou jiné platformy, atribut znamená, že tato platforma není podporována.
V jednom rozhraní API můžete kombinovat a [UnsupportedOSPlatform]
atributy[SupportedOSPlatform]
. V tomto případě platí následující pravidla:
- Seznam povolených položek Pokud je nejnižší verze pro každou platformu
[SupportedOSPlatform]
operačního systému atributem, rozhraní API se považuje za podporované pouze uvedenými platformami a nepodporované všemi ostatními platformami. Seznam může mít atribut se stejnou[UnsupportedOSPlatform]
platformou, ale pouze s vyšší verzí, která označuje, že rozhraní API je z této verze odebráno. - Odepřít seznam. Pokud je nejnižší verze pro každou platformu
[UnsupportedOSPlatform]
operačního systému atributem, rozhraní API se považuje za nepodporované pouze pro uvedené platformy a podporované všemi ostatními platformami. Seznam může mít atribut se stejnou[SupportedOSPlatform]
platformou, ale pouze s vyšší verzí, která označuje, že rozhraní API je od této verze podporované. - Nekonzistentní seznam Pokud je
[SupportedOSPlatform]
nejnižší verze některých platforem, ale[UnsupportedOSPlatform]
pro jiné platformy, považuje se tato kombinace za nekonzistentní. Některé poznámky v rozhraní API se ignorují. V budoucnu můžeme zavést analyzátor, který v případě nekonzistence vytvoří upozornění.
Pokud přistupujete k rozhraní API s poznámkami s těmito atributy z kontextu jiné platformy, můžete zobrazit porušení CA1416.
Cílové platformy TFM
Analyzátor nekontroluje cílové platformy monikeru (TFM) cílové platformy z vlastností NÁSTROJE MSBuild, například <TargetFramework>
nebo <TargetFrameworks>
. Pokud má TFM cílovou platformu, sada .NET SDK vloží SupportedOSPlatform
do souboru AssemblyInfo.cs atribut s názvem cílové platformy, který analyzátor využívá. Pokud je net5.0-windows10.0.19041
například TFM , sada SDK vloží [assembly: System.Runtime.Versioning.SupportedOSPlatform("windows10.0.19041")]
atribut do souboru AssemblyInfo.cs a celé sestavení se považuje pouze za Windows. Proto volání rozhraní API jen pro Windows ve verzi 7.0 nebo novější nezpůsobí žádná upozornění v projektu.
Poznámka:
Pokud je generování souboru AssemblyInfo.cs pro projekt zakázané (to znamená, že <GenerateAssemblyInfo>
vlastnost je nastavena na false
), nelze přidat požadovaný atribut úrovně SupportedOSPlatform
sestavení sadou SDK. V takovém případě se zobrazí upozornění na využití rozhraní API specifická pro konkrétní platformu, i když na tuto platformu cílíte. Pokud chcete upozornění vyřešit, povolte generování AssemblyInfo.cs souboru nebo přidejte atribut do projektu ručně.
Porušení
Pokud přistupujete k rozhraní API, které je podporované jenom na zadané platformě (
[SupportedOSPlatform("platformName")]
) z kódu dostupného na jiných platformách, uvidíte následující porušení: "API" je podporováno na platformě PlatformName.// An API supported only on Linux. [SupportedOSPlatform("linux")] public void LinuxOnlyApi() { } // API is supported on Windows, iOS from version 14.0, and MacCatalyst from version 14.0. [SupportedOSPlatform("windows")] [SupportedOSPlatform("ios14.0")] // MacCatalyst is a superset of iOS, therefore it's also supported. public void SupportedOnWindowsIos14AndMacCatalyst14() { } public void Caller() { LinuxOnlyApi(); // This call site is reachable on all platforms. 'LinuxOnlyApi()' is only supported on: 'linux' SupportedOnWindowsIos14AndMacCatalyst14(); // This call site is reachable on all platforms. 'SupportedOnWindowsIos14AndMacCatalyst14()' // is only supported on: 'windows', 'ios' 14.0 and later, 'MacCatalyst' 14.0 and later. }
Poznámka:
K porušení dojde pouze v případě, že projekt nebude cílit na podporovanou platformu (
net5.0-differentPlatform
). To platí také pro projekty s více cíli. K žádnému porušení nedojde, pokud projekt cílí na zadanou platformu (net5.0-platformName
) a AssemblyInfo.cs generování souborů je pro projekt povolené.Přístup k rozhraní API, které je přiřazeno
[UnsupportedOSPlatform("platformName")]
z kontextu, který cílí na nepodporovanou platformu, může způsobit porušení: "API" není podporováno na platformě PlatformName.// An API not supported on Android but supported on all other platforms. [UnsupportedOSPlatform("android")] public void DoesNotWorkOnAndroid() { } // An API was unsupported on Windows until version 10.0.18362. // The API is considered supported everywhere else without constraints. [UnsupportedOSPlatform("windows")] [SupportedOSPlatform("windows10.0.18362")] public void StartedWindowsSupportFromCertainVersion() { } public void Caller() { DoesNotWorkOnAndroid(); // This call site is reachable on all platforms.'DoesNotWorkOnAndroid()' is unsupported on: 'android' StartedWindowsSupportFromCertainVersion(); // This call site is reachable on all platforms. 'StartedWindowsSupportFromCertainVersion()' is unsupported on: 'windows' 10.0.18362 and before }
Poznámka:
Pokud vytváříte aplikaci, která necílí na nepodporovanou platformu, nebudete dostávat žádná porušení. K porušení dojde pouze v následujících případech:
Projekt cílí na platformu, která je přiřazená jako nepodporovaná.
Je
platformName
součástí výchozí skupiny položek NÁSTROJE MSBuild<SupportedPlatform>
.platformName
je ručně zahrnutý do skupiny položek nástroje MSBuild<SupportedPlatform>
.<ItemGroup> <SupportedPlatform Include="platformName" /> </ItemGroup>
Jak opravit porušení
Doporučeným způsobem řešení porušení je zajistit, abyste při spouštění na příslušné platformě volali pouze rozhraní API specifická pro danou platformu. Toho dosáhnete tak, že kód v době sestavení vyloučíte pomocí #if
a cílení na více verzí, nebo podmíněným voláním kódu za běhu. Analyzátor rozpozná ochranu platformy ve OperatingSystem třídě a System.Runtime.InteropServices.RuntimeInformation.IsOSPlatform.
Potlačte porušení tím, že obklopíte web volání standardními metodami ochrany platformy nebo vlastními rozhraními API ochrany ochrany anotací s SupportedOSPlatformGuardAttribute nebo UnsupportedOSPlatformGuardAttribute.
// An API supported only on Linux. [SupportedOSPlatform("linux")] public void LinuxOnlyApi() { } // API is supported on Windows, iOS from version 14.0, and MacCatalyst from version 14.0. [SupportedOSPlatform("windows")] [SupportedOSPlatform("ios14.0")] // MacCatalyst is a superset of iOS, therefore it's also supported. public void SupportedOnWindowsIos14AndMacCatalyst14() { } public void Caller() { LinuxOnlyApi(); // This call site is reachable on all platforms. 'LinuxOnlyApi()' is only supported on: 'linux'. SupportedOnWindowsIos14AndMacCatalyst14(); // This call site is reachable on all platforms. 'SupportedOnWindowsIos14AndMacCatalyst14()' // is only supported on: 'windows', 'ios' 14.0 and later, 'MacCatalyst' 14.0 and later. } [SupportedOSPlatformGuard("windows")] // The platform guard attributes used [SupportedOSPlatformGuard("ios14.0")] private readonly bool _isWindowOrIOS14 = OperatingSystem.IsWindows() || OperatingSystem.IsIOSVersionAtLeast(14); // The warnings are avoided using platform guard methods. public void Caller() { if (OperatingSystem.IsLinux()) // standard guard examples { LinuxOnlyApi(); // no diagnostic } if (OperatingSystem.IsIOSVersionAtLeast(14)) { SupportedOnWindowsAndIos14(); // no diagnostic } if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { SupportedOnWindowsAndIos14(); // no diagnostic } if (_isWindowOrMacOS14) // custom guard example { SupportedOnWindowsAndIos14(); // no diagnostic } } // An API not supported on Android but supported on all other platforms. [UnsupportedOSPlatform("android")] public void DoesNotWorkOnAndroid() { } // An API was unsupported on Windows until version 10.0.18362. // The API is considered supported everywhere else without constraints. [UnsupportedOSPlatform("windows")] [SupportedOSPlatform("windows10.0.18362")] public void StartedWindowsSupportFromCertainVersion(); public void Caller() { DoesNotWorkOnAndroid(); // This call site is reachable on all platforms.'DoesNotWorkOnAndroid()' is unsupported on: 'android' StartedWindowsSupportFromCertainVersion(); // This call site is reachable on all platforms. 'StartedWindowsSupportFromCertainVersion()' is unsupported on: 'windows' 10.0.18362 and before. } [UnsupportedOSPlatformGuard("android")] // The platform guard attribute bool IsNotAndroid => !OperatingSystem.IsAndroid(); public void Caller() { if (!OperatingSystem.IsAndroid()) // using standard guard methods { DoesNotWorkOnAndroid(); // no diagnostic } // Use the && and || logical operators to guard combined attributes. if (!OperatingSystem.IsWindows() || OperatingSystem.IsWindowsVersionAtLeast(10, 0, 18362)) { StartedWindowsSupportFromCertainVersion(); // no diagnostic } if (IsNotAndroid) // custom guard example { DoesNotWorkOnAndroid(); // no diagnostic } }
Analyzátor také System.Diagnostics.Debug.Assert respektuje jako prostředek, který brání dosažení kódu na nepodporovaných platformách. Použití
Debug.Assert
umožňuje, aby se kontrola v případě potřeby ořízla z buildů vydaných verzí.// An API supported only on Linux. [SupportedOSPlatform("linux")] public void LinuxOnlyApi() { } public void Caller() { Debug.Assert(OperatingSystem.IsLinux()); LinuxOnlyApi(); // No diagnostic }
Můžete se rozhodnout, že vlastní rozhraní API označíte jako specifická pro konkrétní platformu a efektivně předáte požadavky volajícím. Atributy platformy můžete použít na libovolná z následujících rozhraní API:
- Typy
- Členové (metody, pole, vlastnosti a události)
- Sestavení
[SupportedOSPlatform("windows")] [SupportedOSPlatform("ios14.0")] public void SupportedOnWindowsAndIos14() { } [SupportedOSPlatform("ios15.0")] // call site version should be equal to or higher than the API version public void Caller() { SupportedOnWindowsAndIos14(); // No diagnostics } [UnsupportedOSPlatform("windows")] [SupportedOSPlatform("windows10.0.18362")] public void StartedWindowsSupportFromCertainVersion(); [UnsupportedOSPlatform("windows")] [SupportedOSPlatform("windows10.0.18362")] public void Caller() { StartedWindowsSupportFromCertainVersion(); // No diagnostics }
Při použití atributu na úrovni sestavení nebo typu se považují všechny členy v rámci sestavení nebo typu za specifické pro platformu.
[assembly:SupportedOSPlatform("windows")] public namespace ns { public class Sample { public void SupportedOnWindows() { } public void Caller() { SupportedOnWindows(); // No diagnostic as call site and calling method both windows only } } }
Kdy potlačit upozornění
Odkazování na rozhraní API specifická pro platformu bez správného kontextu platformy nebo ochrany se nedoporučuje. Tuto diagnostiku však můžete potlačit příznakem #pragma
kompilátoru NoWarn nebo nastavením závažnosti pravidla na none
soubor .editorconfig .
[SupportedOSPlatform("linux")]
public void LinuxOnlyApi() { }
public void Caller()
{
#pragma warning disable CA1416
LinuxOnlyApi();
#pragma warning restore CA1416
}
Konfigurace kódu pro analýzu
Analyzátor je ve výchozím nastavení povolený jenom pro projekty, které cílí na .NET 5 nebo novější a mají hodnotu AnalysisLevel 5 nebo vyšší. Můžete ji povolit pro cílové architektury nižší než net5.0
přidáním následujícího páru klíč-hodnota do souboru .editorconfig v projektu:
dotnet_code_quality.enable_platform_analyzer_on_pre_net5_target = true
Viz také
- CA1422: Ověření kompatibility platformy
- Analyzátor kompatibility platformy (koncepční)
- Přidávání poznámek k rozhraním API pro konkrétní platformu a zjišťování jejího použití
- Přidávání poznámek k rozhraním API jako nepodporovaných na konkrétních platformách
- Názvy cílových rozhraní v .NET 5
- Pravidla interoperability