Una de las nuevas y llamativas características de C#12 es el soporte para los constructores primarios. El concepto de constructores primarios no es nuevo. Varios lenguajes de programación, incluidos Scala, Kotlin y OCaml, brindan soporte para integrar parámetros de constructor directamente en el lugar donde declara su clase.
En este artículo, analizaremos de cerca los constructores principales y cómo podemos trabajar con ellos en C# 12. Para ejecutar los ejemplos de código proporcionados en este artículo, debe tener Visual Studio 2022 instalado en su sistema. Si aún no tienes una copia, puedes descargue Visual Studio 2022 aquí.
Crear un proyecto de aplicación de consola en Visual Studio
En primer lugar, creemos un proyecto de aplicación de consola .NET Core en Visual Studio. Suponiendo que Visual Studio 2022 esté instalado en su sistema, siga los pasos que se describen a continuación para crear una nueva aplicación de consola .NET Core.
- Inicie el IDE de Visual Studio.
- Haga clic en «Crear nuevo proyecto».
- En la ventana «Crear nuevo proyecto», seleccione «Aplicación de consola (.NET Core)» de la lista de plantillas que se muestran.
- Haga clic en Siguiente.
- En la ventana «Configura tu nuevo proyecto», especifica el nombre y la ubicación del nuevo proyecto.
- Haga clic en Siguiente.
- En la ventana «Información adicional» que se muestra a continuación, elija «.NET 8.0 (soporte a largo plazo)» como la versión del marco que desea utilizar.
- Haga clic en Crear.
Usaremos este proyecto de aplicación de consola .NET 8 para trabajar con constructores principales en las secciones siguientes de este artículo.
¿Qué son los constructores primarios?
Constructores primarios le permite declarar constructores en una clase o estructura con parámetros disponibles en todo el cuerpo del tipo. Usando constructores primarios, puede crear constructores para su clase o estructura sin escribir código, es decir, sin declarar explícitamente miembros de datos privados ni implementar constructores para asignar los valores de los parámetros del constructor a esos miembros de datos.
El siguiente fragmento de código ilustra un constructor primario declarado dentro de una estructura.
public readonly struct Rectangle(double x, double y) { //Members of the struct Rectangle }
A continuación se muestra una implementación simple de un constructor primario declarado dentro de una clase.
public class Rectangle(double x, double y) { //Members of the class Rectangle }
Los parámetros del constructor principal tienen como ámbito la clase en su conjunto. Son accesibles para todos los miembros de la instancia excepto para los constructores secundarios. En C#, el compilador infiere qué campos privados requerimos y captura los valores correspondientes.
Considere el siguiente fragmento de código que implementa un constructor principal para una clase denominada Cliente.
public class Customer(int id, string FirstName, string LastName) { //Implement the class members here }
Las propiedades pertenecientes a esta clase se inicializarán automáticamente utilizando los parámetros del constructor principal.
Pros y contras de los constructores primarios en C#
Los constructores primarios en C# ofrecen tres beneficios clave.
- Sintaxis simplificada: al utilizar constructores primarios, puede declarar e inicializar propiedades directamente dentro de los parámetros del constructor, lo que reduce la duplicación de código.
- Inicialización sencilla: puede aprovechar los constructores primarios para inicializar las propiedades de una clase con valores predeterminados o valores específicos pasados como parámetros del constructor.
- Inmutabilidad: puede aprovechar el modificador init en las propiedades inicializadas en el constructor principal para garantizar que sean de solo lectura después de la inicialización del objeto.
Los constructores primarios en C# también tienen varias desventajas.
- Flexibilidad reducida: los constructores primarios están diseñados para ser simples, lo que puede limitar su flexibilidad. Es posible que no sean adecuados cuando se necesita una lógica de inicialización compleja o cuando se requieren acciones adicionales, como validación, programación o registro.
- Código menos explícito: reducir el código repetitivo es una buena práctica, pero también puede hacer que el código sea menos explícito. Los desarrolladores sin experiencia pueden necesitar ayuda para comprender cómo se inicializan las propiedades o cómo funciona el constructor.
- Problemas de compatibilidad: integrar perfectamente la nueva sintaxis de los constructores primarios en una base de código existente podría ser un desafío, especialmente si la base de código es grande y compleja.
- Control limitado sobre los modificadores de acceso: un constructor primario ofrece menos control sobre los modificadores de acceso que un constructor tradicional. Por lo tanto, los constructores primarios pueden no ser adecuados en escenarios que requieren un control detallado sobre la accesibilidad.
- Curva de aprendizaje: debido a que los constructores principales son nuevos en el lenguaje de programación C#, es posible que sus desarrolladores necesiten tiempo para ponerse al día con su uso, lo que podría ralentizar el desarrollo de su proyecto.
Usar constructores sobrecargados con un constructor primario en C#
Puedes usar constructores sobrecargados en cualquier clase que tenga un constructor principal. El siguiente fragmento de código ilustra cómo se pueden crear varios constructores en una clase que tenga un constructor principal.
public class User(int id, string userName, string password) { //Implement the members of the class here }// Other members of the class }
Uso de constructores primarios en tipos de registros frente a clases en C#
Si bien tanto los registros como las clases admiten constructores primarios, existen diferencias sutiles en el comportamiento. Por ejemplo, así es como puede definir un tipo de registro que utilice un constructor principal:
public record AuthorRecord(int Id, string firstName, string lastName, string address, string phone);
Y así es como puedes definir una clase que use un constructor primario:
public record AuthorClass(int Id, string firstName, string lastName, string address, string phone);
Puede crear una instancia del tipo de registro anterior como se muestra a continuación.
var authorRecord = AuthorRecord(int Id, string firstName, string lastName, string address, string phone);
Sin embargo, si intenta asignar valores a los miembros de datos del tipo de registro de la manera que se muestra a continuación, encontrará un error del compilador.
authorRecord.Id = 1;
Por el contrario, puede crear una instancia del tipo de clase anterior y asignar valores a sus miembros de datos como se muestra a continuación, sin ningún error de compilación.
var authorClass = AuthorClass(int Id, string firstName, string lastName, string address, string phone); authorClass.Id = 1;
Utilice la inyección de dependencia en constructores primarios en C#
Puede aprovechar los constructores primarios al implementar la inyección de dependencias en su aplicación C#. Entendamos esto con un ejemplo. El siguiente código ilustra cómo podemos implementar la inyección de constructor en C#.
public class AuthorService { private readonly IAuthorRepository _authorRepository; public AuthorService(IAuthorRepository authorRepository) { _authorRepository = authorRepository; } public async Task<IEnumerable<Author>> GetAll() { return await _authorRepository.GetAll(); } }
Finalmente, observe cómo se pueden usar los constructores primarios para hacer que su código sea más nítido y limpio, como se muestra en el siguiente código.
public class AuthorService (IAuthorRepository authorRepository) { public async Task<IEnumerable<Author>> GetAll() { return await authorRepository.GetAll(); } }
Aunque los constructores primarios se introdujeron inicialmente en C# 9, se limitaron únicamente a tipos de registros. Con C# 12, puede utilizar constructores primarios en tipos de registros, clases y estructuras, lo que le ayudará a escribir código repetitivo que sea más limpio y conciso.
Copyright © 2024 IDG Communications, Inc.