Destinatarios multiplataforma

La plataforma .NET moderna es compatible con varios sistemas operativos y dispositivos. Es importante para las bibliotecas de código abierto de .NET admitir tantos desarrolladores como sea posible, ya sea que esté creando un sitio web ASP.NET hospedado en Azure o un juego de .NET en Unity.

Destinos de .NET y .NET Standard

.NET y .NET Standard son la mejor manera de agregar compatibilidad multiplataforma a una biblioteca de .NET.

  • .NET Standard es una especificación de API de .NET que se prevé que esté disponible en todas las implementaciones de .NET. El establecimiento de .NET Standard como destino permite generar bibliotecas restringidas a usar las API de una versión concreta de .NET Standard, lo que significa que lo pueden usar todas las plataformas que implementan esa versión de .NET Standard.
  • Las versiones 6 y 8 de .NET son implementaciones de .NET. Cada versión es un único producto con un conjunto uniforme de funcionalidades y API que se pueden usar para aplicaciones de escritorio de Windows y aplicaciones de consola multiplataforma, servicios en la nube y sitios web.

Para más información sobre cómo .NET se compara con .NET Standard, consulte .NET 5 y .NET Standard.

.NET Standard

Aunque su proyecto vaya dirigido a .NET o .NET Standard y se compile correctamente, no quiere decir que la biblioteca se ejecute correctamente en todas las plataformas:

  • Las API específicas de plataforma producirán un error en otras plataformas. Por ejemplo, Microsoft.Win32.Registry se llevará a cabo correctamente en Windows y generará PlatformNotSupportedException cuando se utilice en cualquier otro sistema operativo.
  • Las API pueden comportarse de manera diferente. Por ejemplo, las API de reflexión tienen diferentes características de rendimiento cuando una aplicación utiliza una compilación anticipada en iOS o UWP.

Sugerencia

El equipo de .NET ofrece un analizador de compatibilidad de plataforma para ayudar a detectar posibles problemas.

✔️ EMPIECE por incluir un destino de netstandard2.0.

La mayoría de bibliotecas de uso general no necesitan API fuera de .NET Standard 2.0. Todas las plataformas modernas admiten .NET Standard 2.0 y es la manera recomendada para admitir varias plataformas con un destino. Si no necesita compatibilidad con .NET Framework, podría usar también .NET Standard 2.1.

✔️ Incluya un destino net6.0 o posterior si necesita introducir nuevas API en una versión moderna de .NET.

Las aplicaciones .NET 6 y posterior pueden usar un destino netstandard2.0, por lo que net6.0 no es necesario. Cuando quiera usar API .NET más recientes, debe dirigirse explícitamente a net6.0, net7.0 o net8.0.

❌ EVITE incluir un destino de netstandard1.x.

.NET Standard 1.x se distribuye como un conjunto pormenorizado de paquetes NuGet, que crea un gráfico de dependencias de paquetes grande y da lugar a que los desarrolladores descarguen una gran cantidad de paquetes durante la compilación. Las implementaciones de .NET modernas admiten .NET Standard 2.0. Solo debe utilizar .NET Standard 1.x como destino si necesita específicamente una plataforma anterior como destino.

✔️ INCLUYA un destino de netstandard2.0 si necesita un destino de netstandard1.x.

Todas las plataformas que admiten .NET Standard 2.0 usarán el destino netstandard2.0 y se aprovecharán del hecho de tener un gráfico de paquetes más pequeño, mientras que las plataformas anteriores seguirán funcionando y pasarán a usar el destino netstandard1.x.

❌ NO incluya un destino de .NET Standard si la biblioteca se basa en un modelo de aplicación específico de la plataforma.

Por ejemplo, una biblioteca de Kit de herramientas de control UWP depende de un modelo de aplicación que solo está disponible en UWP. Las API específicas del modelo de aplicación no están disponibles en .NET Standard.

Compatibilidad con múltiples versiones

En ocasiones necesitará tener acceso a las API específicas del marco de las bibliotecas. La mejor manera de llamar a las API específicas del marco es usar varios destinos, de forma que el proyecto se compila para muchas plataformas de destino .NET en lugar de solo para una.

Para evitar que los consumidores tengan que crear para marcos individuales, debe procurar tener una salida de .NET Standard además de una o más salidas específicas del marco. Con varios destinos, todos los ensamblados se empaquetan dentro de un único paquete NuGet. Después, los consumidores pueden hacer referencia al mismo paquete y NuGet seleccionará la implementación apropiada. La biblioteca de .NET Standard actúa como la biblioteca de reserva que se usa en todas partes, salvo en los casos donde el paquete NuGet ofrece una implementación específica del marco. Varios destinos le permiten usar la compilación condicional en el código y llamar a las API específicas del marco.

NuGet package with multiple assemblies

✔️ ES RECOMENDABLE usar las implementaciones de .NET como destino además de .NET Standard.

El uso de las implementaciones de .NET como destino le permite llamar a las API específicas de la plataforma que se encuentran fuera de .NET Standard.

No elimine la compatibilidad con .NET Standard al hacer esto. En su lugar, empiece desde la implementación y ofrezca API de funcionalidad. De este modo, la biblioteca se puede usar en cualquier lugar y admite la activación de características en tiempo de ejecución.

public static class GpsLocation
{
    // This project uses multi-targeting to expose device-specific APIs to .NET Standard.
    public static async Task<(double latitude, double longitude)> GetCoordinatesAsync()
    {
#if NET462
        return CallDotNetFrameworkApi();
#elif WINDOWS_UWP
        return CallUwpApi();
#else
        throw new PlatformNotSupportedException();
#endif
    }

    // Allows callers to check without having to catch PlatformNotSupportedException
    // or replicating the OS check.
    public static bool IsSupported
    {
        get
        {
#if NET462 || WINDOWS_UWP
            return true;
#else
            return false;
#endif
        }
    }
}

✔️ CONSIDERE la posibilidad de usar varios destinos incluso si el código fuente es el mismo para todos los destinos, cuando el proyecto tenga dependencias de bibliotecas o paquetes.

Los paquetes dependientes del proyecto, ya sean directos o descendentes, pueden utilizar las mismas API de código pero envueltas en diferentes versiones del ensamblado dependiente por plataforma de destino. Agregar destinos específicos garantiza que los consumidores no tengan que agregar o actualizar sus redireccionamientos de enlaces de ensamblados.

❌ EVITE el uso de varios destinos, así como el destino .NET Standard, si el código fuente es el mismo para todos los destinos y el proyecto no tiene dependencias de bibliotecas o paquetes.

NuGet usará automáticamente el ensamblado de .NET Standard. El uso de las implementaciones de .NET individuales como destino aumenta el tamaño de *.nupkg sin obtener ventaja alguna.

✔️ ES RECOMENDABLE agregar un destino para net462 cuando se ofrece un destino de netstandard2.0.

El uso de .NET Standard 2.0 de .NET Framework tiene algunos problemas que se han solucionado en .NET Framework 4.7.2. Puede mejorar la experiencia de los desarrolladores que siguen usando .NET Framework 4.6.2 - 4.7.1 ofreciéndoles un archivo binario que se ha compilado para .NET Framework 4.6.2.

✔️ DEBE distribuir las bibliotecas mediante un paquete NuGet.

NuGet seleccionará el mejor destino para el desarrollador y evitará que tenga de tener que elegir la implementación apropiada.

✔️ USE una propiedad TargetFrameworks del archivo de proyecto cuando haya varios destinos.

<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <!-- This project will output netstandard2.0 and net462 assemblies -->
    <TargetFrameworks>netstandard2.0;net462</TargetFrameworks>
  </PropertyGroup>
</Project>

✔️ ES RECOMENDABLE usar MSBuild.Sdk.Extras cuando haya varios destinos para UWP y Xamarin, ya que simplifica considerablemente el archivo de proyecto.

❌ EVITE cambiar el nombre del ensamblado o usar nombres de ensamblado diferentes para cada TFM que compile la biblioteca. Debido a las dependencias entre bibliotecas, un destino múltiple con nombres de ensamblado diferentes por TFM puede interrumpir los consumidores de paquetes. Un ensamblado debe tener el mismo nombre en todos los TFM.

Destinos antiguos

.NET admite como destino las versiones de .NET Framework que han dejado de ser compatibles, así como las plataformas que ya no se usan. Si bien es valioso hacer que la biblioteca funcione en tantos destinos como sea posible, tener que trabajar con API ausentes puede agregar una sobrecarga significativa. Algunos marcos ya no valen la pena como destino, considerando su alcance y limitaciones.

❌ NO incluya un destino de Biblioteca de clases portátil (PCL). Por ejemplo, portable-net45+win8+wpa81+wp8.

.NET standard es la forma moderna de admitir las bibliotecas de .NET multiplataforma y reemplaza a las PCL.

❌ NO incluya destinos para las plataformas de .NET que ya no se admitan. Por ejemplo: SL4, WP.