Consideraciones sobre versiones y actualizaciones para desarrolladores de C#

La compatibilidad es un objetivo muy importante cuando se agregan nuevas características al lenguaje C#. En la mayoría de los casos, se puede volver a compilar el código existente con una nueva versión de compilador sin ningún problema. El equipo del entorno de ejecución de .NET también tiene previsto garantizar la compatibilidad con las bibliotecas actualizadas. En casi todos los casos, cuando se inicia la aplicación desde un entorno de ejecución con bibliotecas actualizadas, el comportamiento es exactamente el mismo que con las versiones anteriores.

La versión del lenguaje que se usa para compilar la aplicación suele coincidir con el moniker de la plataforma de destino en tiempo de ejecución (TFM) al que se hace referencia en el proyecto. Para obtener más información sobre cómo cambiar la versión predeterminada del lenguaje, consulte el artículo Control de versiones del lenguaje C#. Este comportamiento predeterminado garantiza la máxima compatibilidad.

Cuando se introducen cambios importantes, se clasifican del siguiente modo:

  • Cambio importante de código binario: un cambio importante de código binario provoca un comportamiento diferente, incluidos posibles bloqueos, en la aplicación o biblioteca cuando se inicia con un nuevo entorno de ejecución. Debe volver a compilar la aplicación para incorporar estos cambios. El código binario anterior no funcionará correctamente.
  • Cambio importante de código fuente: un cambio importante en el código fuente cambia su significado. Debe modificar el código fuente antes de compilar la aplicación con la versión más reciente del lenguaje. El código binario anterior se ejecutará correctamente con el host y el entorno de ejecución más recientes. Tenga en cuenta que, para la sintaxis del lenguaje, un cambio importante de código fuente también es un cambio de comportamiento, como se define en los cambios importantes del entorno de ejecución.

Cuando un cambio importante de código binario afecta a la aplicación, debe volver a compilar la aplicación, pero no es necesario editar ningún código fuente. Cuando un cambio importante de código fuente afecta a la aplicación, el código binario anterior se sigue ejecutando correctamente en sistemas que tienen el entorno de ejecución y las bibliotecas actualizados. Sin embargo, debe realizar cambios en el código fuente para volver a compilar la aplicación con la nueva versión del lenguaje y el entorno de ejecución. En el caso de un cambio importante tanto de código binario como de código fuente, debe volver a compilar la aplicación con la versión más reciente y actualizar el código fuente.

Debido al objetivo que tienen los equipos del lenguaje C# y del entorno de ejecución de evitar cambios importantes, la actualización de la aplicación suele ser una cuestión de actualizar el TFM y recompilar la aplicación. Sin embargo, para las bibliotecas que se distribuyen públicamente, debe evaluar cuidadosamente su directiva de TFM admitidos y las versiones de lenguaje admitidas. Puede crear una biblioteca con características que se encuentran en la última versión y necesita asegurarse de que las aplicaciones creadas con versiones anteriores del compilador pueden usarla. O bien puede actualizar una biblioteca con la posibilidad de que muchos de los usuarios aún no tengan versiones actualizadas.

Introducción de cambios importantes en bibliotecas

Cuando adopte nuevas características de lenguaje en la API pública de la biblioteca, debe evaluar si la adopción de la característica presenta un cambio importante de código binario o de código fuente para los usuarios de la biblioteca. Los cambios en la implementación interna que no aparecen en las interfaces public o protected son compatibles.

Nota:

Si usa System.Runtime.CompilerServices.InternalsVisibleToAttribute para permitir que los tipos muestren los miembros internos, estos miembros internos pueden introducir cambios importantes.

Un cambio importante de código binario requiere que los usuarios vuelvan a compilar el código para usar la nueva versión. Por ejemplo, considere este método público:

public double CalculateSquare(double value) => value * value;

Si agrega el modificador in al método, se trata de un cambio importante de código binario:

public double CalculateSquare(in double value) => value * value;

Los usuarios deben volver a compilar cualquier aplicación que use el método CalculateSquare para que la nueva biblioteca funcione correctamente.

Un cambio importante de código fuente requiere que los usuarios cambien el código antes de volver a compilar la aplicación. Por ejemplo, considere este tipo:

public class Person
{
    public string FirstName { get; }
    public string LastName { get; }

    public Person(string firstName, string lastName) => (FirstName, LastName) = (firstName, lastName);

    // other details omitted
}

En una versión más reciente, le gustaría aprovechar las ventajas de los miembros sintetizados generados para los tipos record. Realice el siguiente cambio:

public record class Person(string FirstName, string LastName);

El cambio anterior requiere modificaciones en cualquier tipo derivado de Person. Todas esas declaraciones deben agregar el modificador record a sus declaraciones.

Impacto de los cambios importantes

Al agregar un cambio importante de código binario a la biblioteca, se obliga a que todos los proyectos que usen la biblioteca se vuelvan a compilar. Sin embargo, no es necesario modificar el código fuente de esos proyectos. Por tanto, el impacto del cambio importante es razonablemente pequeño para cada proyecto.

Al realizar un cambio importante de código fuente en la biblioteca, es necesario cambiar el código fuente de todos los proyectos para que usen la nueva biblioteca. Si el cambio necesario requiere nuevas características del lenguaje, obliga a actualizar esos proyectos a la misma versión del lenguaje y el TFM que usa ahora. Ha requerido más trabajo para los usuarios y, posiblemente, también los ha obligado a actualizar la aplicación.

El impacto de cualquier cambio importante que realice depende del número de proyectos que tengan una dependencia de la biblioteca. Si algunas aplicaciones internas usan la biblioteca, puede reaccionar ante cualquier cambio importante en todos los proyectos afectados. Sin embargo, si la biblioteca se descarga públicamente, debe evaluar el posible impacto y considerar alternativas:

  • Agregar nuevas API que funcionen en paralelo con las API actuales.
  • Compilaciones paralelas para diferentes TFM.
  • Compatibilidad con múltiples versiones.