Tabla de Contenido
0. Introducción1. Structs
2. Diferencias entre Structs y Clases
3. Declaración de un Struct
4. Estructura de Almacenamiento: ¿Heap o Stack?
5. Herencia y Constructores
6. Implementación de Interfaces
7. Semántica de Construcción de Structs
8. Conclusiones
9. Glosario
10. Enlaces & Literatura
0. Introducción
Vamos
a describir otro de las construcciones reusables que puede ser creadas en el
lenguaje de programación C#: los structs
(tipos por valor). Veremos un contraste entre este tipo de dato y las clases.
Al igual, la utilidad estas construcciones de tipos en aplicaciones.
Finalmente, veremos algunos apuntes acerca de la ganancia de rendimiento.
¡Empecemos!
1. Structs
Un estructura es una construcción que representa un tipo por valor, y normalmente se usan para encapsular conjuntos de variables con una relación en particular. Ejemplos de uso de structs:
- Coordenadas de un punto en un plano cartesiano.
- Características de un elemento en un inventario.
En general podemos decir que un struct es un útil en ambientes en donde es necesario las operaciones y estados de los tipos por valor.
Por otro lado, nosotros ya conocemos operaciones de asignación sobre tipos numéricos como:
int x = 5;
double y;
y = 3.14159;
char character = 'j';
Es evidente que la asignación de memoria (como en el caso de los objetos) no es necesaria para este tipo de estructura, sólo nos basta asignar un valor literal (e.g., 5, 3.14159, o 'j') al identificador: en pocas palabras la instanciación no es necesaria (se puede omitir el uso de new [4])
2. Diferencias entre structs y clases
En la declaración sintáctica y uso, los structs son similares a las, sin embargo existen sutiles diferencias; entre esas tenemos:
- Una clase es de tipo por referencia, mientras que un struct es de tipo por valor.
- En los structs no está soportada la herencia.
- Sólo está permitida, implícitamente, la herencia de System.ValueType [5]. (Evidentemente, este último hereda de Object -cfr. La Clase Object y sus Miembros en C#-).
- Un struct sólo puede implementar interfaces, mientras que una clase puede heredar de una clase, y también implementar una o varias interfaces.
- Un struct no puede contener:
- Constructor sin parámetros
- Un finalizador -cfr. Liberación de Recursos y Finalizadores en C#-
- Miembros virtuales -cfr. Miembros Función Virtuales en C#-.
3. Declaración de un struct
Declaración básica de un tipo de valor con la palabra clave struct [3]:
Archivo Libro.cs:
En este struct se declaran tres campos: uno de tipo por valor (precio: decimal), y dos por referencia (titulo y autor: string). Obsérvese que la declaración del struct Libro sigue, análogamente, las mismas convenciones de una clase:
- Modifcador de acceso: en este caso public.
- Especificador de tipo: para Libro, struct.
- Nombre del tipo de la estructura: Libro
4. Estructura de almacenamiento: ¿Heap o Stack?
Cuando creamos una referencia de una clase, el contenido de éste es almacenado en la memoria stack -cfr. Variables y Parámetros en C# - Parte 1-. Esto no ocurre con un struct, ya que es colocado en la memoria heap -cfr. Ídem-, inclusive cuando utilizamos el operador new para crear el struct.
En el siguiente ejemplo observaremos que cuando pasamos un struct como argumento sobre un método, éste es pasado por valor. Observemos:
Archivo StructsComoArgumentos.cs:
> Prueba de ejecución.
Cuando ejecutamos el código cliente de este ejemplo, obtenemos el resultado:
esto se debe a que la variable ms es pasada por valor (se genera un copia en el pase) por la misma naturaleza de los structs. Mientras que mc si afecta el campo en la asignación del miembro Campo en el cuerpo del método CambiarValorClase.
public struct MiStruct
{
public MiStruct()
{
}
}
Por otro lado, cuando intentamos heredar de una estructura, este es el error que se produce en tiempo de compilación:
public struct MiBase
{
}
public struct MiStruct
{
}
Archivo de código fuente ImplementacionInterfacesEnStructs.cs:
Cuando ejecutamos el código cliente de este ejemplo, obtenemos el resultado:
Valor de ms.Campo = 3 Valor de mc.Campo = 7
esto se debe a que la variable ms es pasada por valor (se genera un copia en el pase) por la misma naturaleza de los structs. Mientras que mc si afecta el campo en la asignación del miembro Campo en el cuerpo del método CambiarValorClase.
5. Constructores y Herencia
Como mencionamos en la sección 2, un struct puede declarar constructores pero todos deben tener parámetros, de lo contrario se generará el error:public struct MiStruct
{
public MiStruct()
{
}
}
prog.cs(18,16): error CS0568: Structs cannot contain explicit parameterless constructors
Por otro lado, cuando intentamos heredar de una estructura, este es el error que se produce en tiempo de compilación:
public struct MiBase
{
}
public struct MiStruct
{
}
prog.cs(21,26): error CS0527: Type `StructBase' in interface list is not an interface
6. Implementación de Interfaces
Para los structs si está permitida la operación de implementación de interfaces. Veamos este ejemplo:Archivo de código fuente ImplementacionInterfacesEnStructs.cs:
7. Semántica de Construcción de Structs
Cuando definimos o construimos un struct debemos seguir estas reglas:
- Intentar sobrescribir un constructor sin parámetros generará un error en tiempo de compilación. Los structs ya poseen, de manera implícita, un constructor sin parámetros que lleva a cabo la inicialización a los valores por defecto de los campos.
- No está permitido la asignación (inicializadores) de valores a los campos en su defnición.
- La definición de un constructor requiere de explícitamente cada campo.
A través de un ejemplo:
public struct Punto
{
int x = 1; // Ilegal: No se puede inicializar un campo
int y;
public Punto() // Ilegal: No se puede tener un constructor sin parámetros
{
}
public Punto(int x) // Ilegal: Se debe asignar un valor a y
{
this.x = x;
}
}
8. Conclusiones
Aprendimos los esenciales de los structs en C#. Vimos cómo declara un struct utilizando la palabra reservada struct. Por otro lado diferenciamos entre clase y struct: la primera es un tipo por referencia, la segunda un tipo por valor. Luego vimos que los structs, por su misma naturaleza son localizados en la memoria heap para ganar rendimiento. Luego vimos que nos es posible practicar la herencia en los structs. Al final vimos que sí es posible la implementación de interfaces en los structs.
9. Glosario
- Estructura
- Heap
- Stack
- Tipo por referencia
- Tipo por valor
10. Enlaces & Literatura
[1]: C# 5.0 in a Nutshell by Joseph Albahari and Ben Albahari. Copyright 2012 Joseph Albahari and Ben Albahari, 978-1-449-32010-2.[2]: Structs Tutorial (C#) - http://msdn.microsoft.com/en-us/library/aa288471%28v=vs.71%29.aspx
[3]: struct (C# Reference) - http://msdn.microsoft.com/en-us/library/vstudio/ah19swz4%28v=vs.110%29.aspx
[4]: new (C# Reference) - http://msdn.microsoft.com/en-us/library/51y09td4.aspx
[5]: ValueType Class (System) - http://msdn.microsoft.com/en-us/library/system.valuetype%28v=vs.110%29.aspx
[6]: La Clase Object y sus Miembros en C# | OrtizOL - Experiencias Construcción Software (xCSw) - http://ortizol.blogspot.com/2014/04/la-clase-object-y-sus-miembros-en-c.html
[7]: Liberación de Recursos y Finalizadores en C# | OrtizOL - Experiencias Construcción Software (xCSw) - http://ortizol.blogspot.com/2013/10/liberacion-de-recursos-y-finalizadores.html
[8]: Miembros Función Virtuales en C# | OrtizOL - Experiencias Construcción Software (xCSw) - http://ortizol.blogspot.com/2013/12/miembros-funcion-virtuales-en-c.html
[9]: Variables y Parámetros en C# - Parte 1 | OrtizOL - Experiencias Construcción Software (xCSw) - http://ortizol.blogspot.com/2013/09/variables-y-parametros-en-c-parte-1.html
J
No hay comentarios:
Publicar un comentario
Envíe sus comentarios, dudas, sugerencias, críticas. Gracias.