Sí, C # 8 se puede usar con .NET Framework y otros destinos anteriores a .NET Core 3.0 / .NET Standard 2.1 en Visual Studio 2019 (o versiones anteriores de Visual Studio si instala un paquete Nuget ).
La versión de idioma debe establecerse en 8.0
en el archivo csproj.
La mayoría de las funciones, pero no todas, están disponibles en cualquier marco de referencia.
Características que funcionan
Las siguientes funciones son solo cambios de sintaxis; funcionan independientemente del marco:
Funciones que se pueden hacer funcionar
Estos requieren nuevos tipos que no están en .NET Framework. Solo se pueden usar junto con paquetes o archivos de código "polyfill" Nuget:
Miembros de interfaz predeterminados: no funcionan
Los miembros de la interfaz predeterminada no se compilarán en .NET Framework y nunca funcionarán porque requieren cambios de tiempo de ejecución en CLR. El .NET CLR ahora está congelado, ya que .NET Core es ahora el camino a seguir.
Para obtener más información sobre lo que funciona y lo que no, y sobre posibles polyfills, consulte el artículo de Stuart Lang, C # 8.0 y .NET Standard 2.0 - Doing Unsupported Things .
Código
El siguiente proyecto de C # que tiene como destino .NET Framework 4.8 y utiliza tipos de referencia que aceptan valores NULL C # 8 se compila en Visual Studio 16.2.0. Lo creé eligiendo la plantilla Biblioteca de clases estándar de .NET y luego editándola para apuntar a .NET Framework en su lugar:
.csproj:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>net48</TargetFrameworks>
<LangVersion>8.0</LangVersion>
<Nullable>enable</Nullable>
</PropertyGroup>
</Project>
.cs:
namespace ClassLibrary1
{
public class Class1
{
public string? NullableString { get; set; }
}
}
Luego probé un proyecto de .NET Framework 4.5.2 WinForms, usando un .csproj
formato heredado , y agregué la misma propiedad de tipo de referencia anulable. Cambié el tipo de idioma en el cuadro de diálogo de configuración de Visual Studio Advanced Build (deshabilitado en 16.3) latest
y guardé el proyecto. Por supuesto que este punto no se construye. Abrí el archivo del proyecto en un editor de texto y cambié latest
a preview
en la configuración de compilación PropertyGroup
:
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<LangVersion>preview</LangVersion>
Luego habilité la compatibilidad con tipos de referencia que aceptan valores NULL agregando <Nullable>enable</Nullable>
a la principal PropertyGroup
:
<PropertyGroup>
<Nullable>enable</Nullable>
Recargué el proyecto y se compila.
Los detalles sangrientos
Cuando se escribió esta respuesta por primera vez, C # 8 estaba en vista previa y se involucró mucho trabajo de detective. Aquí dejo esa información para la posteridad. Siéntase libre de omitirlo si no necesita conocer todos los detalles sangrientos.
Históricamente, el lenguaje C # ha sido mayoritariamente neutral en cuanto al marco , es decir, capaz de compilar versiones anteriores del marco, aunque algunas características han requerido nuevos tipos o compatibilidad con CLR.
La mayoría de los entusiastas de C # habrán leído la entrada del blog Building C # 8.0 de Mads Torgersen, que explica que ciertas características de C # 8 tienen dependencias de plataforma:
Los flujos, indexadores y rangos asíncronos se basan en nuevos tipos de marcos que serán parte de .NET Standard 2.1 ... .NET Core 3.0, así como Xamarin, Unity y Mono implementarán .NET Standard 2.1, pero .NET Framework 4.8 lo hará no. Esto significa que los tipos necesarios para utilizar estas funciones no estarán disponibles en .NET Framework 4.8.
Esto se parece un poco a las tuplas de valor que se introdujeron en C # 7. Esa característica requería nuevos tipos, las ValueTuple
estructuras, que no estaban disponibles en las versiones de NET Framework por debajo de 4.7 o .NET Standard anteriores a 2.0. Sin embargo , C # 7 aún podría usarse en versiones anteriores de .NET, ya sea sin tuplas de valor o con ellas instalando el paquete System.ValueTuple Nuget . Visual Studio entendió esto y todo estaba bien con el mundo.
Sin embargo, Mads también escribió:
Por esta razón, el uso de C # 8.0 solo se admite en plataformas que implementan .NET Standard 2.1.
... que, de ser cierto, habría descartado el uso de C # 8 con cualquier versión de .NET Framework, y de hecho incluso en las bibliotecas .NET Standard 2.0 que solo recientemente se nos animó a usar como destino de referencia para el código de la biblioteca. Ni siquiera podría usarlo con versiones de .NET Core anteriores a 3.0, ya que también son compatibles con .NET Standard 2.0.
¡La investigación estaba en marcha! -
Jon Skeet tiene una versión alfa de Noda-Time que usa C # 8 lista para usar y que se dirige solo a .NET Standard 2.0. Claramente espera que C # 8 / .NET Standard 2.0 sea compatible con todos los marcos de la familia .NET. (Consulte también la publicación del blog de Jon "Primeros pasos con tipos de referencia que aceptan valores NULL" ).
Los empleados de Microsoft han estado discutiendo la interfaz de usuario de Visual Studio para los tipos de referencia que aceptan valores NULL de C # 8 en GitHub , y se afirma que tienen la intención de admitir el legado csproj
(formato del SDK anterior a .NET Core csproj
). Esta es una indicación muy clara de que C # 8 se podrá utilizar con .NET Framework. [Sospecho que retrocederán en esto ahora que el menú desplegable de la versión de idioma de Visual Studio 2019 se ha deshabilitado y .NET se ha vinculado a C # 7.3]
Poco después de la famosa publicación del blog, un hilo de GitHub discutió el soporte multiplataforma. Un punto importante que surgió fue que .NET Standard 2.1 incluirá un marcador que indica que se admiten implementaciones predeterminadas de interfaces ; la función requiere un cambio de CLR que nunca estará disponible para .NET Framework. Aquí está lo importante, de Immo Landwerth, administrador de programas en el equipo .NET de Microsoft:
Se espera que los compiladores (como C #) utilicen la presencia de este campo para decidir si permitir o no implementaciones de interfaz predeterminadas. Si el campo está presente, se espera que el tiempo de ejecución pueda cargar y ejecutar el código resultante.
Todo esto apuntaba a que "C # 8.0 solo es compatible con plataformas que implementan .NET Standard 2.1" siendo una simplificación excesiva, y que C # 8 admitirá .NET Framework pero, como hay tanta incertidumbre, pregunté en GitHub y HaloFour respondió:
IIRC, la única característica que definitivamente no aparecerá en .NET Framework es DIM (métodos de interfaz predeterminados) ya que requiere cambios en el tiempo de ejecución. Las otras características están impulsadas por la forma de las clases que es posible que nunca se agreguen a .NET Framework, pero que se pueden rellenar mediante su propio código o NuGet (rangos, índices, iteradores asíncronos, eliminación asíncrona).
Victor Derks comentó que "Los nuevos atributos que aceptan valores NULL necesarios para diseñar los casos de uso que aceptan valores NULL más complejos solo están disponibles en System.Runtime.dll que se envía con .NET Core 3.0 y .NET Standard 2.1 ... [y] incompatible con .NET Framework 4.8 "
Sin embargo, Immo Landwerth comentó que "La gran mayoría de nuestras API no necesitaban atributos personalizados, ya que los tipos son completamente genéricos o no nulos" en el artículo Pruebe los tipos de referencia que aceptan valores NULL.
Ben Hall planteó el problema de Disponibilidad de atributos que aceptan valores NULL fuera de Core 3.0 en GitHub, destacando los siguientes comentarios de los empleados de Microsoft:
C # 8 será totalmente compatible con .net core 3.0 y .net estándar 2.1 únicamente. Si edita manualmente el archivo de proyecto para usar C # 8 con .net core 2.1, se encuentra en territorio no admitido. Algunas características de C # 8 funcionarán bien, algunas características de C # 8 no funcionarán demasiado bien (por ejemplo, un rendimiento deficiente), algunas características de C # 8 funcionarán con hacks adicionales y algunas características de C # 8 no funcionarán en absoluto. Muy complejo de explicar. No lo bloqueamos activamente para que los usuarios expertos que puedan navegar por él puedan hacerlo. No recomendaría este mix & match no admitido para un uso amplio.
(Jan Kotas)
Las personas como usted que están dispuestas a entender y trabajar con ellas son libres de usar C # 8. El punto es que no todas las características del lenguaje funcionarán en objetivos de nivel inferior.
(Immo Landwerth)
Visual Studio 2019
Ha habido un cambio importante en la versión RTM de Visual Studio 2019 versión 16.3: la versión de lanzamiento para C # 8.0: el menú desplegable de selección de idioma se ha deshabilitado:
El fundamento de Microsoft para esto es:
En el futuro, ... cada versión de cada marco tendrá una única versión compatible y predeterminada, y no admitiremos versiones arbitrarias. Para reflejar este cambio en el soporte, esta confirmación deshabilita permanentemente el cuadro combinado de versión de idioma y agrega un enlace a un documento que explica el cambio.
El documento que se abre es el control de versiones en lenguaje C # . Esto enumera C # 8.0 como el idioma predeterminado para .NET Core 3.x SOLAMENTE. También confirma que , en el futuro, cada versión de cada marco tendrá una única versión compatible y predeterminada y que ya no se puede confiar en el agnosticismo del marco del lenguaje.
La versión de idioma aún se puede forzar a 8 para proyectos de .NET Framework editando el archivo .csproj.
Advertencia emptor
Microsoft no admite oficialmente la combinación C # 8 / .NET Framework. Es, dicen, solo para expertos.