Nota
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare ad accedere o modificare le directory.
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare a modificare le directory.
| Proprietà | valore |
|---|---|
| ID regola | CA1416 |
| Title | Convalida compatibilità della piattaforma |
| Categoria | Interoperabilità |
| La correzione causa un'interruzione o meno | Non causa un'interruzione |
| Abilitato per impostazione predefinita in .NET 10 | Come avviso |
Causa
Le violazioni vengono segnalate se un'API specifica della piattaforma viene usata nel contesto di una piattaforma diversa o se la piattaforma non è verificata (indipendente dalla piattaforma). Le violazioni vengono segnalate anche se viene usata un'API non supportata per la piattaforma di destinazione del progetto.
Questa regola è abilitata per impostazione predefinita solo per i progetti destinati a .NET 5 o versione successiva. È tuttavia possibile abilitarlo per i progetti destinati ad altri framework.
Descrizione regola
.NET 5 ha aggiunto nuovi attributi SupportedOSPlatformAttribute e UnsupportedOSPlatformAttribute, per annotare le API specifiche della piattaforma. È possibile creare un'istanza di entrambi gli attributi con o senza numeri di versione come parte del nome della piattaforma. Possono anche essere applicati più volte con piattaforme diverse.
- Un'API non annotata viene considerata funzionante in tutte le piattaforme del sistema operativo.
- Un'API contrassegnata con
[SupportedOSPlatform("platformName")]è considerata portabile solo per le piattaforme del sistema operativo specificate. Se la piattaforma è un subset di un'altra piattaforma, l'attributo implica che tale piattaforma è supportata anche. - Un'API contrassegnata con
[UnsupportedOSPlatform("platformName")]viene considerata non supportata nelle piattaforme del sistema operativo specificate. Se la piattaforma è un subset di un'altra piattaforma, l'attributo implica che anche tale piattaforma non è supportata.
È possibile combinare [SupportedOSPlatform] attributi e [UnsupportedOSPlatform] in una singola API. In questo caso, si applicano le regole seguenti:
-
Consenti elenco. Se la versione più bassa per ogni piattaforma del sistema operativo è un attributo
[SupportedOSPlatform], l'API viene considerata supportata solo dalle piattaforme elencate e non supportata da tutte le altre piattaforme. L'elenco può avere un[UnsupportedOSPlatform]attributo con la stessa piattaforma, ma solo con una versione successiva, che indica che l'API viene rimossa da tale versione. -
Elenco di rifiuto. Se la versione più bassa per ogni piattaforma del sistema operativo è un attributo
[UnsupportedOSPlatform], l'API viene considerata non supportata solo dalle piattaforme elencate e supportata da tutte le altre piattaforme. L'elenco può avere un[SupportedOSPlatform]attributo con la stessa piattaforma, ma solo con una versione successiva, che indica che l'API è supportata da tale versione. -
Elenco di elementi incoerenti. Se la versione più bassa per alcune piattaforme è
[SupportedOSPlatform]ma[UnsupportedOSPlatform]per altre piattaforme, questa combinazione viene considerata incoerente. Alcune annotazioni nell'API vengono ignorate. In futuro, è possibile introdurre un analizzatore che genera un avviso in caso di incoerenza.
Se si accede a un'API annotata con questi attributi dal contesto di una piattaforma diversa, è possibile visualizzare violazioni CA1416.
Piattaforme di destinazione TFM
L'analizzatore non controlla le piattaforme di destinazione del moniker framework di destinazione (TFM) dalle proprietà di MSBuild, ad esempio <TargetFramework> o <TargetFrameworks>. Se tfm ha una piattaforma di destinazione, .NET SDK inserisce un SupportedOSPlatform attributo con il nome della piattaforma di destinazione nel file AssemblyInfo.cs , utilizzato dall'analizzatore. Ad esempio, se il TFM è net5.0-windows10.0.19041, l'SDK inserisce l'attributo [assembly: System.Runtime.Versioning.SupportedOSPlatform("windows10.0.19041")] nel file AssemblyInfo.cs e l'intero assembly viene considerato solo Windows. Pertanto, la chiamata di API solo Windows con versione 7.0 o precedente non provocherebbe avvisi nel progetto.
Nota
Se la generazione di file AssemblyInfo.cs è disabilitata per il progetto ( ovvero la <GenerateAssemblyInfo> proprietà è impostata su false), l'attributo a livello SupportedOSPlatform di assembly richiesto non può essere aggiunto dall'SDK. In questo caso è possibile che vengano visualizzati avvisi per l'utilizzo di API specifiche della piattaforma anche se la piattaforma specifica è stata impostata come destinazione. Per risolvere gli avvisi, abilitare la generazione del file AssemblyInfo.cs o aggiungere manualmente l'attributo nel progetto.
Violazioni
Se si accede a un'API supportata solo in una piattaforma specificata (
[SupportedOSPlatform("platformName")]) dal codice raggiungibile in altre piattaforme, verrà visualizzata la violazione seguente: 'API' è supportata in '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. }Nota
Una violazione si verifica solo se il progetto non ha come destinazione la piattaforma supportata (
net5.0-differentPlatform). Questo vale anche per i progetti con più destinazioni. Non si verifica alcuna violazione se il progetto è destinato alla piattaforma specificata (net5.0-platformName) e la generazione di file AssemblyInfo.cs è abilitata per il progetto.L'accesso a un'API con attributo da
[UnsupportedOSPlatform("platformName")]un contesto destinato alla piattaforma non supportata potrebbe generare una violazione: 'API' non è supportata in '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 }
Nota
Se stai creando un'app che non ha come destinazione la piattaforma non supportata, non riceverai alcuna violazione. Una violazione si verifica solo nei casi seguenti:
Il progetto è destinato alla piattaforma con attributi non supportati.
è
platformNameincluso nel gruppo di elementi MSBuild<SupportedPlatform>predefinito.platformNameè incluso manualmente nel gruppo di elementi di MSBuild<SupportedPlatform>.<ItemGroup> <SupportedPlatform Include="platformName" /> </ItemGroup>
Come correggere le violazioni
Il modo consigliato per gestire le violazioni consiste nell'assicurarsi di chiamare solo API specifiche della piattaforma durante l'esecuzione in una piattaforma appropriata. A tale scopo, è possibile escludere il codice in fase di compilazione usando #if e multitargeting oppure chiamando in modo condizionale il codice in fase di esecuzione. L'analizzatore riconosce le guardie della piattaforma nella OperatingSystem classe e System.Runtime.InteropServices.RuntimeInformation.IsOSPlatform.
Eliminare le violazioni circondando il sito di chiamata con i metodi di protezione della piattaforma standard o le API di protezione personalizzata annotate con SupportedOSPlatformGuardAttribute o 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 } }L'analizzatore rispetta System.Diagnostics.Debug.Assert anche come mezzo per impedire che il codice venga raggiunto su piattaforme non supportate. L'uso
Debug.Assertdi consente di tagliare il controllo dalle build di versione, se necessario.// An API supported only on Linux. [SupportedOSPlatform("linux")] public void LinuxOnlyApi() { } public void Caller() { Debug.Assert(OperatingSystem.IsLinux()); LinuxOnlyApi(); // No diagnostic }È possibile scegliere di contrassegnare le proprie API come specifiche della piattaforma, inoltrando efficacemente i requisiti ai chiamanti. È possibile applicare gli attributi della piattaforma a una delle API seguenti:
- Tipi
- Membri (metodi, campi, proprietà ed eventi)
- Assembly
[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 }Quando viene applicato un attributo a livello di assembly o di tipo, tutti i membri all'interno dell'assembly o del tipo vengono considerati specifici della piattaforma.
[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 } } }
Quando eliminare gli avvisi
Non è consigliabile fare riferimento ad API specifiche della piattaforma senza un contesto di piattaforma appropriato o protezione. Tuttavia, è possibile eliminare questi dati di diagnostica usando #pragma o il flag del compilatore NoWarn oppure impostando la gravità della regola su none in un file con estensione editorconfig.
[SupportedOSPlatform("linux")]
public void LinuxOnlyApi() { }
public void Caller()
{
#pragma warning disable CA1416
LinuxOnlyApi();
#pragma warning restore CA1416
}
Configurare il codice da analizzare
L'analizzatore è abilitato per impostazione predefinita solo per i progetti destinati a .NET 5 o versione successiva e hanno un valore AnalysisLevel di 5 o versione successiva. È possibile abilitarla per i framework di destinazione inferiori a net5.0 aggiungendo la coppia chiave-valore seguente a un file con estensione editorconfig nel progetto:
dotnet_code_quality.enable_platform_analyzer_on_pre_net5_target = true
Vedi anche
- CA1422: Convalidare la compatibilità della piattaforma
- Analizzatore compatibilità della piattaforma (concettuale)
- Annotare le API specifiche della piattaforma e rilevarne l'uso
- Annotare le API come non supportate in piattaforme specifiche
- Nomi dei framework di destinazione in .NET 5
- Regole di interoperabilità