C# Estructura (Struct)

En C#, una estructura (struct) es un tipo de valor (value type) que se utiliza para organizar y almacenar datos relacionados.

En C#, una estructura es un tipo de datos de valor, lo que permite que una única variable pueda almacenar datos relacionados de varios tipos de datos.

structLa palabra clave se utiliza para crear una estructura.

Una estructura se utiliza para representar un registro. Supongamos que desea realizar un seguimiento de los movimientos de los libros en una biblioteca; es posible que desee realizar un seguimiento de los siguientes atributos de cada libro:

  • Title
  • Author
  • Subject
  • Book ID

Definir una estructura

Para definir una estructura, debe utilizarstructla instrucción.

structLa instrucción define un nuevo tipo de datos con varios miembros para el programa.

Por ejemplo, puede declarar la estructura Book de la siguiente manera:

struct Books
{
   public string title;
   public string author;
   public string subject;
   public int book_id;
};  

El siguiente programa demuestra el uso de las estructuras:

Ejemplo

using System;
using System.Text;
     
struct Books
{
   public string title;
   public string author;
   public string subject;
   public int book_id;
};  

public class testStructure
{
   public static void Main(string[] args)
   {

      Books Book1;        /* Declara Book1, de tipo Books */
      Books Book2;        /* Declara Book2, de tipo Books */

      /* Detalles de book 1 */
      Book1.title = "C Programming";
      Book1.author = "Nuha Ali";
      Book1.subject = "C Programming Tutorial";
      Book1.book_id = 6495407;

      /* Detalles de book 2 */
      Book2.title = "Telecom Billing";
      Book2.author = "Zara Ali";
      Book2.subject =  "Telecom Billing Tutorial";
      Book2.book_id = 6495700;

      /* Imprime la información de Book1 */
      Console.WriteLine( "Book 1 title : {0}", Book1.title);
      Console.WriteLine("Book 1 author : {0}", Book1.author);
      Console.WriteLine("Book 1 subject : {0}", Book1.subject);
      Console.WriteLine("Book 1 book_id :{0}", Book1.book_id);

      /* Imprime la información de Book2 */
      Console.WriteLine("Book 2 title : {0}", Book2.title);
      Console.WriteLine("Book 2 author : {0}", Book2.author);
      Console.WriteLine("Book 2 subject : {0}", Book2.subject);
      Console.WriteLine("Book 2 book_id : {0}", Book2.book_id);      

      Console.ReadKey();

   }
}

Cuando el código anterior se compila y ejecuta, produce los siguientes resultados:

Book 1 title : C Programming
Book 1 author : Nuha Ali
Book 1 subject : C Programming Tutorial
Book 1 book_id : 6495407
Book 2 title : Telecom Billing
Book 2 author : Zara Ali
Book 2 subject : Telecom Billing Tutorial
Book 2 book_id : 6495700

Características de las estructuras en C#

Las estructuras proporcionan un tipo de datos ligero, adecuado para representar estructuras de datos simples, con buenas características de rendimiento y semántica de valor:

  • Las estructuras pueden tener métodos, campos, indexadores, propiedades, métodos de operadores y eventos, y son adecuadas para representar datos ligeros, como coordenadas, rangos, fechas, horas, etc.
  • Las estructuras pueden definir constructores, pero no pueden definir destructores. Sin embargo, no puede definir un constructor sin parámetros para una estructura. El constructor sin parámetros (predeterminado) se define automáticamente y no se puede cambiar.
  • A diferencia de las clases, las estructuras no pueden heredar de otras estructuras o clases.
  • Las estructuras no pueden ser la estructura base de otras estructuras o clases.
  • Las estructuras pueden implementar una o más interfaces.
  • Los miembros de una estructura no pueden especificarse como abstract, virtual o protected.
  • Cuando utiliza elNewoperador para crear un objeto de estructura, se llama al constructor adecuado para crear la estructura. A diferencia de las clases, las estructuras pueden instanciarse sin utilizar el operador New.
  • Si no se utiliza el operador New, solo después de que todos los campos hayan sido inicializados, los campos son asignados y el objeto es utilizado.
  • Las variables de estructura generalmente se asignan en la pila (stack), lo que hace que su creación y destrucción sean más rápidas. Sin embargo, si una estructura se utiliza como campo de una clase, y esa clase es un tipo de referencia, entonces la estructura se almacenará en el montón (heap).
  • Las estructuras son mutables por defecto, lo que significa que puede modificar sus campos. Sin embargo, si una estructura se define como de solo lectura, sus campos serán inmutables.

Clase vs Estructura

Las clases y las estructuras tienen diferentes consideraciones de diseño y uso. Las clases son adecuadas para representar objetos y comportamientos complejos, admiten herencia y polimorfismo, mientras que las estructuras son más adecuadas para representar datos ligeros y tipos de valor, para mejorar el rendimiento y evitar la sobrecarga de gestión de referencias.

Las clases y las estructuras tienen las siguientes diferencias básicas:

Tipo de valor vs Tipo de referencia:

  • Las estructuras son tipos de valor (Value Type):Las estructuras son tipos de valor; asignan memoria en la pila, no en el montón. Cuando se pasa una instancia de estructura a un método o se asigna a otra variable, se copia todo el contenido de la estructura.
  • Las clases son tipos de referencia (Reference Type):Las clases son tipos de referencia; asignan memoria en el montón. Cuando se pasa una instancia de clase a un método o se asigna a otra variable, en realidad se pasa la referencia (dirección de memoria), no una copia del objeto completo.

Herencia y polimorfismo:

  • Las estructuras no pueden heredar:Las estructuras no pueden heredar de otras estructuras o clases, ni pueden ser la clase base de otras estructuras o clases.
  • Las clases admiten herencia:Las clases admiten herencia y polimorfismo; se puede ampliar la funcionalidad de una clase existente derivando nuevas clases.

Constructor predeterminado:

  • Las estructuras no pueden tener un constructor sin parámetros:Las estructuras no pueden contener un constructor sin parámetros.
  • Las clases pueden tener un constructor sin parámetros:Las clases pueden contener un constructor sin parámetros. Si no se proporciona un constructor, el sistema proporciona un constructor predeterminado sin parámetros.

Comportamiento de asignación:

  • Una variable de tipo clase almacena una referencia al asignarse, por lo que dos variables apuntan al mismo objeto.
  • Una variable de estructura copia toda la estructura al asignarse, por lo que cada variable tiene su propia copia independiente.

Forma de paso (paso de parámetros):

  • Los objetos de tipo clase se pasan por referencia en las llamadas a métodos, lo que significa que los cambios realizados al objeto dentro del método afectarán al objeto original.
  • Los objetos de estructura generalmente se pasan por valor, lo que significa que se pasa una copia de la estructura, no el objeto de estructura original en sí. Por lo tanto, los cambios realizados a la estructura dentro de un método no afectarán al objeto original.

Anulabilidad (nullable):

  • Una estructura es un tipo de valor y no se puede establecer directamente comonull:porquenulles el valor predeterminado de un tipo de referencia, no el valor predeterminado de un tipo de valor. Si necesita representar el estado ausente o no válido de una variable de estructura, puede utilizarNullable<T>o también llamadoT?tipo anulable.
  • Las clases pueden ser null por defecto:Una instancia de clase puede ser, por defecto,null, porque son tipos de referencia.

Rendimiento y asignación de memoria:

  • Las estructuras suelen ser más ligeras:Debido a que las estructuras son tipos de valor y asignan memoria en la pila, suelen ser más ligeras que las clases y son adecuadas para la representación de datos simples.
  • Las clases pueden tener más sobrecarga:Debido a que las clases son tipos de referencia, pueden implicar más sobrecarga y gestión de memoria.

En el siguiente ejemplo, MyStruct es una estructura y MyClass es una clase.

La parte de los comentarios demuestra que una estructura no puede contener un constructor sin parámetros, no puede heredar, y que la copia de una instancia de estructura copia todo el contenido de la estructura. Por el contrario, una clase puede contener un constructor sin parámetros, puede heredar, y la copia de una instancia copia la referencia.

Ejemplo

using System;

// Declaración de estructura
struct MyStruct
{
    public int X;
    public int Y;

    // Una estructura no puede tener un constructor sin parámetros
    // public MyStruct()
    // {
    // }

    // Constructor con parámetros
    public MyStruct(int x, int y)
    {
        X = x;
        Y = y;
    }

    // Una estructura no puede heredar
    // struct MyDerivedStruct : MyBaseStruct
    // {
    // }
}

// Declaración de clase
class MyClass
{
    public int X;
    public int Y;

    // Una clase puede tener un constructor sin parámetros
    public MyClass()
    {
    }

    // Constructor con parámetros
    public MyClass(int x, int y)
    {
        X = x;
        Y = y;
    }

    // Las clases admiten herencia
    // class MyDerivedClass : MyBaseClass
    // {
    // }
}

class Program
{
    static void Main()
    {
        // La estructura es un tipo de valor, se asigna en la pila
        MyStruct structInstance1 = new MyStruct(1, 2);
        MyStruct structInstance2 = structInstance1; // Copia toda la estructura

        // La clase es un tipo de referencia, se asigna en el montón
        MyClass classInstance1 = new MyClass(3, 4);
        MyClass classInstance2 = classInstance1; // Copia la referencia, apunta al mismo objeto

        // Modificar una instancia de estructura no afecta a otras instancias
        structInstance1.X = 5;
        Console.WriteLine($"Struct: {structInstance1.X}, {structInstance2.X}");

        // Modificar una instancia de clase afecta a otras instancias
        classInstance1.X = 6;
        Console.WriteLine($"Class: {classInstance1.X}, {classInstance2.X}");
    }
}

En respuesta a la discusión anterior, reescribamos el ejemplo anterior:

Ejemplo

using System;
using System.Text;
     
struct Books
{
   private string title;
   private string author;
   private string subject;
   private int book_id;
   public void setValues(string t, string a, string s, int id)
   {
      title = t;
      author = a;
      subject = s;
      book_id =id;
   }
   public void display()
   {
      Console.WriteLine("Title : {0}", title);
      Console.WriteLine("Author : {0}", author);
      Console.WriteLine("Subject : {0}", subject);
      Console.WriteLine("Book_id :{0}", book_id);
   }

};  

public class testStructure
{
   public static void Main(string[] args)
   {

      Books Book1 = new Books(); /* Declara Book1, de tipo Books */
      Books Book2 = new Books(); /* Declara Book2, de tipo Books */

      /* Detalles de book 1 */
      Book1.setValues("C Programming",
      "Nuha Ali", "C Programming Tutorial",6495407);

      /* Detalles de book 2 */
      Book2.setValues("Telecom Billing",
      "Zara Ali", "Telecom Billing Tutorial", 6495700);

      /* Imprime la información de Book1 */
      Book1.display();

      /* Imprime la información de Book2 */
      Book2.display();

      Console.ReadKey();

   }
}

Cuando el código anterior se compila y ejecuta, produce los siguientes resultados:

Title : C Programming
Author : Nuha Ali
Subject : C Programming Tutorial
Book_id : 6495407
Title : Telecom Billing
Author : Zara Ali
Subject : Telecom Billing Tutorial
Book_id : 6495700
Otras extensiones