El enlace proporcionado por Tejs (http://www.jaggersoft.com/pubs/StructsVsClasses.htm) es una buena explicación (aunque está un poco desactualizado, particularmente en la explicación de los eventos).
La diferencia práctica más importante es que una estructura es un tipo de valor, lo que significa que se pasa por el valor en lugar de hacerlo por referencia. Lo que esto realmente significa es que cuando una estructura se pasa como argumento, en realidad se pasa por copia. Como resultado, las operaciones en una instancia de una estructura no afectan otras instancias.
Considere el siguiente código:
struct NumberStruct
{
public int Value;
}
class NumberClass
{
public int Value = 0;
}
class Test
{
static void Main()
{
NumberStruct ns1 = new NumberStruct();
NumberStruct ns2 = ns1;
ns2.Value = 42;
NumberClass nc1 = new NumberClass();
NumberClass nc2 = nc1;
nc2.Value = 42;
Console.WriteLine("Struct: {0}, {1}", ns1.Value, ns2.Value);
Console.WriteLine("Class: {0}, {1}", nc1.Value, nc2.Value);
}
}
Debido a que tanto ns1
y ns2
son del tipo NumberStruct
valor, cada uno tiene su propio lugar de almacenamiento, por lo que la asignación de ns2.Number
no afecta al valor de ns1.Number
. Sin embargo, dado que nc1
y nc2
son ambos tipos de referencia, la asignación de nc2.Number
afecta el valor de nc1.Number
porque ambos contienen la misma referencia.
[NB El código anterior y texto tomado de Sams Teach Yourself Visual C# 2010 in 24 Hours]
Además, como ya se ha señalado, estructuras deben ser siempre inmutable. (Sí, en este ejemplo, la estructura es mutable pero fue para ilustrar el punto.) Parte de eso significa que las estructuras no deben contener campos públicos.
Dado que las estructuras son tipos de valores, no se puede heredar de una estructura. Tampoco puede derivar una estructura de una clase base. (Sin embargo, una estructura puede implementar interfaces.)
Una estructura tampoco puede tener un contstructor público predeterminado declarado explícitamente (sin parámetros). Cualquier constructor adicional que declare debe inicializar completamente todos los campos de estructura. Structs tampoco puede tener un destructor declarado explícitamente.
Dado que las estructuras son tipos de valores, no deben implementar IDisposable
y no deben contener código no administrado.
Las estructuras realmente no tienen un constructor predeterminado público. Por el contrario, las estructuras que son parte de alguna otra entidad (por ejemplo, elementos de una matriz o campos dentro de una clase, o campos de otra estructura que cumplen los criterios anteriores) * implícitamente * entran en existencia cuando la entidad que los posee aparece sin ningún * * se llama al constructor, mientras que las instancias de clase solo aparecen cuando se instancian explícitamente, lo que, sin Reflection, solo puede ocurrir al invocar un constructor o mediante un método de clase que invoca 'MemberwiseClone'. – supercat
Las estructuras tienen un constructor predeterminado público en todos los sentidos de la palabra: puede invocarlo, puede descubrirlo a través de Reflection, y satisface la restricción 'new()' del tipo genérico. El hecho de que haya formas de construir una estructura sin llamar explícitamente a un constructor de este tipo no la hace desaparecer repentinamente :) – Timwi
La reflexión con estructuras es extraña. Las entidades reales de tipos de estructuras "reales" están fuera del sistema de tipo .net, pero cada tipo de estructura tiene un tipo de clase correspondiente que deriva de 'ValueType'; .net proporciona un operador de conversión cada vez más amplio de cada tipo de estructura a 'Object/ValueType' (que lo convierte en un objeto de clase) y un molde de reducción del objeto de clase a la estructura" real ". Cuando uno usa Reflection para crear una nueva instancia de una estructura, lo que será createde es una derivada ValueType; si uno lo lanza y lo asigna a una estructura, se convertirá en ese tipo de estructura. – supercat