1 puntos por GN⁺ 2024-08-09 | 1 comentarios | Compartir por WhatsApp

Resumen

Es un documento que propone type unions (o discriminated unions) en C#.

Motivación

  • Al desarrollar software, los valores almacenados en una variable no siempre tienen que ser del mismo tipo.
  • Por ejemplo, si las definiciones de cliente y proveedor solo comparten algunas propiedades, puede ser necesario realizar operaciones similares sobre ambos tipos.
  • Esto puede resolverse mediante herencia, pero no es adecuado para todas las situaciones.
  • En C#, se necesita una forma de almacenar un número limitado de tipos distintos en una misma variable.
  • Otros lenguajes ya ofrecen esta funcionalidad.

Solución

  • La forma más adecuada de implementar union types en C# puede verse como una jerarquía con una clase base abstracta.
  • Sin embargo, esto tiene problemas como las restricciones de la jerarquía y la imposibilidad de representar unions de tipos no relacionados.
  • Pueden ser necesarios varios tipos de unions, y esta propuesta los clasifica en cuatro categorías.

Estándar - clases union

Declaración

  • Las clases union se declaran de forma similar a un enum.
  • Cada miembro puede tener variables de estado.

Creación

  • Se crean asignando una instancia del tipo miembro.

Desestructuración

  • Se desestructuran mediante pruebas de tipo y pattern matching.

Exhaustividad

  • Si todos los tipos miembro se consideran en una expresión o instrucción switch, no se necesita un caso predeterminado.

Nullabilidad

  • Se puede incluir null usando la notación estándar de nullabilidad.

Implementación

  • Las clases union se implementan como record classes abstractas.

Especialización - structs union

Declaración

  • Se declaran de forma similar a las clases union, pero agregando la palabra clave struct.

Creación

  • Se crean asignando una instancia del tipo miembro.

Desestructuración

  • Se desestructuran mediante pruebas de tipo y pattern matching.

Exhaustividad

  • Si todos los tipos miembro se consideran en una expresión o instrucción switch, no se necesita un caso predeterminado.

Nullabilidad

  • Se puede incluir null usando la notación estándar de nullabilidad.

Valor predeterminado

  • Un struct union puede quedar en un estado indefinido si no se asigna o si se le asigna el valor predeterminado.

Implementación

  • Los structs union se implementan como structs, y los tipos miembro se implementan como nested record structs.

Temporales - unions ad hoc

Sintaxis

  • Los unions ad hoc se referencian usando la sintaxis de patrón or.

Nomenclatura

  • Se les puede dar un nombre común usando un alias using de archivo o global.

Creación

  • Se crean asignando una instancia del tipo miembro.

Desestructuración

  • Se desestructuran mediante pruebas de tipo y pattern matching.

Exhaustividad

  • Si todos los tipos miembro se consideran en una expresión o instrucción switch, no se necesita un caso predeterminado.

Nullabilidad

  • Se puede incluir null usando la notación estándar de nullabilidad.

Intercambiabilidad

  • Los unions ad hoc con los mismos tipos miembro son intercambiables.

Unions definidos por el usuario

  • Se pueden declarar tipos union que no pueden expresarse como clases union o structs union.
  • La jerarquía puede cerrarse usando el atributo Closed.
  • También pueden implementarse como un wrapper struct usando el atributo Union.

Unions comunes

Option

  • Es un struct union que representa un valor que puede existir o no existir.

Result

  • Es un struct union que devuelve desde una función un resultado exitoso o un error.

Propuestas relacionadas

Jerarquía cerrada

  • Declara un conjunto cerrado de subtipos para un tipo base abstracto usando el atributo Closed.

Valores singleton

  • Los tipos con el atributo singleton pueden usarse como valores en contextos sin tipo.

Atajo para miembros anidados

  • Permite enlazar miembros estáticos o tipos anidados del tipo objetivo usando nombres no enlazados.

Resumen de GN⁺

  • Este documento propone type unions en C#, ofreciendo una forma de almacenar varios tipos en una variable según la situación.
  • Es un intento de introducir en C# una funcionalidad que otros lenguajes ya ofrecen.
  • Puede ayudar a los desarrolladores a mejorar la legibilidad y el mantenimiento del código.
  • Un ejemplo de otro lenguaje con una funcionalidad similar es F#.

1 comentarios

 
GN⁺ 2024-08-09
Opiniones de Hacker News
  • Había usado uniones discriminadas en F# y pensó que también existirían en C#

    • Está usando Java y siente que es difícil volver a un lenguaje sin ADT
    • Le alegra no tener que seguir disculpándose por una carencia importante de C#
  • El término "unión de tipos" le resulta poco familiar

    • Parece similar a las tagged unions de los lenguajes de la familia ML
    • Se pregunta si los desarrolladores de C# tienden a crear nombres distintos a la terminología ya existente
  • Como desarrollador veterano de C#, siente que el caso de uso de esta propuesta no está claro

    • Parece que podría implementarse declarando una interfaz vacía y clases record
    • Se pregunta si hay algo que se le esté escapando
  • TypeScript tiene uniones de tipos

    • Parecen similares a las uniones discriminadas de F# o Haskell
    • Las uniones discriminadas tienen constructores de caso con nombre
  • Programar se vuelve difícil sin uniones que permitan pattern matching

    • No había entendido por completo el significado del problema de la expresión
    • Los puntos de extensión mediante polimorfismo existente pueden ser adecuados para clientes futuros
    • Para el código que posee el equipo, las uniones con pattern matching resultan más adecuadas
  • Tiene experiencia con uniones en C# usando field offsets

    • Los valores de puntero/referencia y el aliasing de valores pueden provocar comportamiento indefinido
    • Una unión de struct entre u64 y un objeto puede requerir un campo separado, desperdiciando 8 bytes
  • Usa constructores privados y un paquete de nuget para que un switch type no requiera el caso _

    • Es similar a una versión desazucarada de la "clase unión" propuesta
    • Le parece bien que el paquete de nuget deje de ser necesario y que se agregue azúcar sintáctica
  • No se menciona cómo un union struct maneja el tearing durante modificaciones concurrentes

    • El tearing puede causar problemas de seguridad de memoria
    • Puede haber variantes con un campo entero y un campo de referencia en el mismo offset