Nota
L'accés a aquesta pàgina requereix autorització. Podeu provar d'iniciar la sessió o de canviar els directoris.
L'accés a aquesta pàgina requereix autorització. Podeu provar de canviar els directoris.
| Propiedad | Valor |
|---|---|
| Identificador de la regla | CA1416 |
| Título | Validación de la compatibilidad con las plataformas |
| Categoría | Interoperabilidad |
| La corrección interrumpe o no interrumpe | Sin interrupción |
| Habilitado de forma predeterminada en .NET 10 | Como advertencia |
| Idiomas aplicables | C# y Visual Basic |
Causa
Las infracciones se detectan si se usa una API específica de la plataforma en el contexto de una plataforma diferente o si no se comprueba la plataforma (independiente de la plataforma). También se muestran las infracciones si se usa una API incompatible con la plataforma de destino del proyecto.
Esta regla está habilitada de forma predeterminada, solo para los proyectos que tienen como destino .NET 5 o una versión posterior. Sin embargo, puede habilitarlo para los proyectos que tienen como destino otros marcos de trabajo.
Descripción de la regla
En .NET 5 se han agregado nuevos atributos, SupportedOSPlatformAttribute y UnsupportedOSPlatformAttribute, para anotar las API específicas de la plataforma. Se puede crear una instancia de ambos atributos con o sin números de versión como parte del nombre de la plataforma. También se pueden aplicar varias veces con otras plataformas.
- Se considera que una API sin anotar funciona en todas las plataformas de sistema operativo (SO).
- Una API marcada con
[SupportedOSPlatform("platformName")]solo se considera portable a las plataformas del sistema operativo especificado. Si la plataforma es un subconjunto de otra plataforma, el atributo implica que también se admite esa plataforma. - Una API marcada con
[UnsupportedOSPlatform("platformName")]se considera incompatible con las plataformas del sistema operativo especificado. Si la plataforma es un subconjunto de otra plataforma, el atributo implica que esa plataforma tampoco se admite.
Puede combinar los atributos [SupportedOSPlatform] y [UnsupportedOSPlatform] en una sola API. En este caso, se aplican las siguientes reglas:
-
Lista de permitidos. Si la versión más antigua de cada plataforma de sistema operativo es un atributo
[SupportedOSPlatform], se considera que la API solo es compatible con las plataformas de la lista y no es compatible con todas las demás plataformas. La lista puede tener un atributo[UnsupportedOSPlatform]con la misma plataforma, pero solo con una versión posterior, lo que indica que la API se ha eliminado de esa versión. -
Lista de denegación. Si la versión más antigua de cada plataforma de sistema operativo es un atributo
[UnsupportedOSPlatform], se considerará que la API no es compatible únicamente con las plataformas enumeradas y sí es compatible con todas las demás plataformas. La lista puede tener un atributo[SupportedOSPlatform]con la misma plataforma, pero solo con una versión posterior, lo que indica que la API se admite desde esa versión. -
Lista de incoherentes: Si la versión mínima para algunas plataformas es
[SupportedOSPlatform], pero es[UnsupportedOSPlatform]para otras, esta combinación se considera incoherente. Se omiten algunas anotaciones de la API. En el futuro, es posible que se introduzca un analizador que genere una advertencia en caso de incoherencia.
Si accede a una API anotada con estos atributos desde el contexto de otra plataforma, puede ver infracciones de CA1416.
Plataformas de destino de TFM
El analizador no comprueba los identificadores de framework objetivo (TFM) de las plataformas objetivo desde las propiedades de MSBuild, como <TargetFramework> o <TargetFrameworks>. Si el TFM tiene una plataforma de destino, .NET SDK inserta un atributo SupportedOSPlatform con el nombre de la plataforma de destino en el archivo AssemblyInfo.cs, que el analizador consume. Por ejemplo, si el TFM es net5.0-windows10.0.19041, SDK inserta el atributo [assembly: System.Runtime.Versioning.SupportedOSPlatform("windows10.0.19041")] en el archivo AssemblyInfo.cs y se considera que todo el ensamblado es solo para Windows. Por tanto, la llamada a las API exclusivas de Windows con la versión 7.0 o inferior no provocaría ninguna advertencia en el proyecto.
Nota
Si la generación de archivos AssemblyInfo.cs está deshabilitada para el proyecto (es decir, la propiedad <GenerateAssemblyInfo> está establecida en false), SDK no puede agregar el atributo SupportedOSPlatform de nivel de ensamblado necesario. En este caso, podría ver advertencias sobre el uso de API específicas de la plataforma, aunque tenga como destino esa plataforma. Para resolver las advertencias, habilite la generación de archivos AssemblyInfo.cs o agregue el atributo manualmente en el proyecto.
Infracciones
Si accede a una API que solo es compatible con una plataforma especificada (
[SupportedOSPlatform("platformName")]) con código accesible en otras plataformas, verá la siguiente infracción: "API" es compatible con "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
Solo se produce una infracción si el proyecto no tiene como destino la plataforma compatible (
net5.0-differentPlatform). Esto también se aplica a los proyectos con destinos múltiples. No se produce ninguna infracción si el proyecto tiene como destino la plataforma especificada (net5.0-platformName) y la generación de archivos AssemblyInfo.cs está habilitada para el proyecto.El acceso a una API que tiene el atributo
[UnsupportedOSPlatform("platformName")]en un contexto que tiene como destino la plataforma no compatible podría producir una infracción: "API" no es compatible con "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
Si está desarrollando una aplicación que no está destinada a una plataforma no compatible, no incurrirá en ninguna violación. Solo se produce una infracción en los casos siguientes:
El proyecto apunta a la plataforma que se considera no admitida.
platformNameestá incluido en el grupo predeterminado de elementos de MSBuild<SupportedPlatform>.platformNamese incluye manualmente en el grupo de elementos de MSBuild<SupportedPlatform>.<ItemGroup> <SupportedPlatform Include="platformName" /> </ItemGroup>
Cómo corregir infracciones
La manera recomendada de tratar las infracciones es asegurarse de que solo se llama a las API específicas de la plataforma cuando se ejecuta en una plataforma adecuada. Puede lograr esto excluyendo el código en tiempo de compilación utilizando #if y multidestino, o llamando condicionalmente al código en tiempo de ejecución. El analizador reconoce las restricciones de la plataforma en la clase OperatingSystem y en System.Runtime.InteropServices.RuntimeInformation.IsOSPlatform.
Para suprimir las infracciones, rodea el sitio de llamada con los métodos estándar de protección de la plataforma o con las API personalizadas de protección, anotadas 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 } }El analizador también respeta System.Diagnostics.Debug.Assert como un medio para evitar que el código se alcance en plataformas no compatibles. El uso de
Debug.Assertpermite recortar la comprobación de las compilaciones de versión, si así se desea.// An API supported only on Linux. [SupportedOSPlatform("linux")] public void LinuxOnlyApi() { } public void Caller() { Debug.Assert(OperatingSystem.IsLinux()); LinuxOnlyApi(); // No diagnostic }Puede elegir marcar sus propias APIs como específicas de la plataforma y reenviar eficazmente los requisitos a los llamadores. Puede aplicar los atributos de plataforma a cualquiera de las siguientes API:
- Tipos
- Miembros (métodos, campos, propiedades y eventos)
- Ensamblados
[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 }Cuando se aplica un atributo a nivel de ensamblado o de tipo, se considera que todos los miembros dentro del ensamblado o tipo son específicos de la plataforma.
[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 } } }
Cuándo suprimir las advertencias
No se recomienda hacer referencia a las API específicas de la plataforma sin un contexto de plataforma o una restricción adecuados. Puedes suprimir estos diagnósticos usando #pragma o el indicador de compilador NoWarn, o bien puedes ajustar el nivel de severidad de la regla a none en un archivo .editorconfig.
[SupportedOSPlatform("linux")]
public void LinuxOnlyApi() { }
public void Caller()
{
#pragma warning disable CA1416
LinuxOnlyApi();
#pragma warning restore CA1416
}
Configuración del código para analizar
El analizador está habilitado de manera predeterminada solo para los proyectos que tienen como destino .NET 5 o posterior, y tienen un valor de AnalysisLevel de 5 o superior. Puede habilitarlo para las plataformas de destino inferiores a net5.0 agregando el siguiente par clave-valor a un archivo .editorconfig en el proyecto:
dotnet_code_quality.enable_platform_analyzer_on_pre_net5_target = true
Consulte también
- CA1422: Validación de la compatibilidad con las plataformas
- Analizador de compatibilidad de plataformas (conceptual)
- Anotación de API específicas de la plataforma y detección de su uso
- Anotación de las API como no compatibles en plataformas específicas
- Nombres de plataformas de destino en .NET 5
- Reglas de interoperabilidad