.net - una - estructuras de datos en c#




¿Cuál es la diferencia entre estructura y clase en.NET? (12)

¿Cuál es la diferencia entre estructura y clase en .NET?


Las estructuras son el valor real: pueden estar vacías pero nunca nulas

Esto es cierto, sin embargo, también tenga en cuenta que a partir de .NET 2, las estructuras admiten una versión de Nullable y C # proporciona algo de azúcar sintáctico para que sea más fácil de usar.

int? value = null;
value  = 1;

  1. Los eventos declarados en una clase tienen sus accesos + = y - = bloqueados automáticamente a través de un bloqueo (esto) para hacerlos seguros para los hilos (los eventos estáticos están bloqueados en el tipo de clase). Los eventos declarados en una estructura no tienen su acceso + = y - = bloqueado automáticamente. Un bloqueo (esto) para una estructura no funcionaría ya que solo se puede bloquear en una expresión de tipo de referencia.

  2. La creación de una instancia de estructura no puede provocar una recolección de elementos no utilizados (a menos que el constructor cree directa o indirectamente una instancia de tipo de referencia), mientras que la creación de una instancia de tipo de referencia puede causar la recolección de elementos no utilizados.

  3. Una estructura siempre tiene un constructor público predeterminado incorporado.

    class DefaultConstructor
    {
        static void Eg()
        {
            Direct     yes = new   Direct(); // Always compiles OK
            InDirect maybe = new InDirect(); // Compiles if constructor exists and is accessible
            //...
        }
    }
    

    Esto significa que una estructura es siempre instanciable mientras que una clase podría no serlo ya que todos sus constructores podrían ser privados.

    class NonInstantiable
    {
        private NonInstantiable() // OK
        {
        }
    }
    
    struct Direct
    {
        private Direct() // Compile-time error
        {
        }
    }
    
  4. Una estructura no puede tener un destructor. Un destructor es solo una anulación del objeto. Finalice de manera disfrazada, y las estructuras, al ser tipos de valor, no están sujetas a recolección de basura.

    struct Direct
    {
        ~Direct() {} // Compile-time error
    }
    class InDirect
    {
        ~InDirect() {} // Compiles OK
    }
    
    And the CIL for ~Indirect() looks like this:
    
    .method family hidebysig virtual instance void
            Finalize() cil managed
    {
      // ...
    } // end of method Indirect::Finalize
    
  5. Una estructura está implícitamente sellada, una clase no.
    Una estructura no puede ser abstracta, una clase puede.
    Una estructura no puede llamar a: base () en su constructor, mientras que una clase sin una clase base explícita puede hacerlo.
    Una estructura no puede extender otra clase, una clase puede.
    Una estructura no puede declarar miembros protegidos (por ejemplo, campos, tipos anidados) una clase puede.
    Una estructura no puede declarar miembros de funciones abstractas, una clase abstracta puede.
    Una estructura no puede declarar miembros de funciones virtuales, una clase puede.
    Una estructura no puede declarar miembros de funciones selladas, una clase puede.
    Una estructura no puede declarar miembros de la función de anulación, una clase puede.
    La única excepción a esta regla es que una estructura puede anular los métodos virtuales de System.Object, viz, Equals () y GetHashCode (), y ToString ().


Además de todas las diferencias descritas en las otras respuestas:

  1. Las estructuras no pueden tener un constructor explícito sin parámetros mientras que una clase puede
  2. Las estructuras no pueden tener destructores , mientras que una clase puede
  3. Las estructuras no pueden heredar de otra estructura o clase, mientras que una clase puede heredar de otra clase. (Tanto las estructuras como las clases pueden implementarse desde una interfaz).

Si está buscando un video que explique todas las diferencias, puede consultar la Parte 29: Tutorial de C #: diferencia entre clases y estructuras en C # .


Bueno, para empezar, una estructura se pasa por valor en lugar de por referencia. Las estructuras son buenas para estructuras de datos relativamente simples, mientras que las clases tienen mucha más flexibilidad desde un punto de vista arquitectónico a través del polimorfismo y la herencia.

Probablemente, otros pueden brindarte más detalles que yo, pero uso structs cuando la estructura que busco es simple.


Como se mencionó anteriormente: las clases son de tipo de referencia, mientras que las estructuras son tipos de valor con todas las consecuencias.

Como un pulgar de la regla, las pautas de diseño de marcos recomiendan usar Structs en lugar de clases si:

  • Tiene un tamaño de instancia inferior a 16 bytes.
  • Lógicamente representa un solo valor, similar a los tipos primitivos (int, double, etc.)
  • Es inmutable
  • No tendrá que ser boxeado con frecuencia.

De elegir de Microsoft entre clase y Struct ...

Como regla general, la mayoría de los tipos en un marco deben ser clases. Sin embargo, existen algunas situaciones en las que las características de un tipo de valor hacen que sea más apropiado utilizar estructuras.

CONSIDERA una estructura en lugar de una clase:

  • Si las instancias del tipo son pequeñas y suelen durar poco o están comúnmente incrustadas en otros objetos.

X EVITE una estructura a menos que el tipo tenga todas las características siguientes:

  • Lógicamente representa un solo valor, similar a los tipos primitivos (int, double, etc.).
  • Tiene un tamaño de instancia inferior a 16 bytes.
  • Es inmutable. (no puede ser cambiado)
  • No tendrá que ser boxeado con frecuencia.

En .NET, hay dos categorías de tipos, tipos de referencia y tipos de valor .

Las estructuras son tipos de valor y las clases son tipos de referencia .

La diferencia general es que un tipo de referencia vive en el montón, y un tipo de valor vive en línea, es decir, donde sea que esté definida su variable o campo.

Una variable que contiene un tipo de valor contiene todo el valor del tipo de valor. Para una estructura, eso significa que la variable contiene la estructura completa, con todos sus campos.

Una variable que contiene un tipo de referencia contiene un puntero, o una referencia a otro lugar en la memoria donde reside el valor real.

Esto tiene un beneficio, para empezar con:

  • tipos de valor siempre contiene un valor
  • los tipos de referencia pueden contener una referencia nula , lo que significa que no se refieren a nada en este momento

Internamente, los tipos de referencia se implementan como indicadores, y sabiendo que, y sabiendo cómo funciona la asignación de variables, existen otros patrones de comportamiento:

  • al copiar el contenido de una variable de tipo de valor en otra variable, se copia todo el contenido en la nueva variable, lo que hace que los dos sean distintos. En otras palabras, después de la copia, los cambios a uno no afectarán al otro.
  • al copiar el contenido de una variable de tipo de referencia en otra variable, se copia la referencia, lo que significa que ahora tiene dos referencias al mismo almacenamiento en otro lugar de los datos reales. En otras palabras, después de la copia, cambiar los datos en una referencia parecerá que también afecta a la otra, pero solo porque en realidad solo estás mirando los mismos datos en ambos lugares.

Cuando declara variables o campos, aquí es cómo difieren los dos tipos:

  • variable: el tipo de valor vive en la pila, el tipo de referencia vive en la pila como un puntero a algún lugar en la memoria del montón donde vive la memoria real (aunque tenga en cuenta la serie de artículos de Eric Lipperts: La pila es un detalle de implementación ).
  • class / struct-field: el tipo de valor vive completamente dentro del tipo, el tipo de referencia vive dentro del tipo como un puntero a algún lugar en la memoria del montón donde vive la memoria real.

En .NET, las declaraciones de estructura y clase diferencian entre tipos de referencia y tipos de valor.

Cuando se pasa un tipo de referencia, solo hay uno almacenado. Todo el código que accede a la instancia está accediendo al mismo.

Cuando se pasa un tipo de valor, cada uno es una copia. Todo el código está trabajando en su propia copia.

Esto se puede mostrar con un ejemplo:

struct MyStruct 
{
    string MyProperty { get; set; }
}

void ChangeMyStruct(MyStruct input) 
{ 
   input.MyProperty = "new value";
}

...

// Create value type
MyStruct testStruct = new MyStruct { MyProperty = "initial value" }; 

ChangeMyStruct(testStruct);

// Value of testStruct.MyProperty is still "initial value"
// - the method changed a new copy of the structure.

Para una clase esto sería diferente.

class MyClass 
{
    string MyProperty { get; set; }
}

void ChangeMyClass(MyClass input) 
{ 
   input.MyProperty = "new value";
}

...

// Create reference type
MyClass testClass = new MyClass { MyProperty = "initial value" };

ChangeMyClass(testClass);

// Value of testClass.MyProperty is now "new value" 
// - the method changed the instance passed.

Las clases no pueden ser nada, la referencia puede apuntar a un nulo.

Las estructuras son el valor real: pueden estar vacías pero nunca nulas. Por esta razón, las estructuras siempre tienen un constructor predeterminado sin parámetros, necesitan un "valor de inicio".


Las instancias de clases se almacenan en el montón administrado. Todas las variables que 'contienen' una instancia son simplemente una referencia a la instancia en el montón. Al pasar un objeto a un método, se pasa una copia de la referencia, no el objeto en sí.

Las estructuras (técnicamente, los tipos de valor) se almacenan donde se usan, de manera muy similar a un tipo primitivo. El tiempo de ejecución puede copiar el contenido en cualquier momento y sin invocar un constructor de copia personalizado. Pasar un tipo de valor a un método implica copiar todo el valor, nuevamente sin invocar ningún código personalizable.

La distinción se hace mejor por los nombres de C ++ / CLI: "clase ref" es una clase como se describe primero, "clase de valor" es una clase como se describe segundo. Las palabras clave "clase" y "estructura" utilizadas por C # son simplemente algo que debe aprenderse.


Para agregar a las otras respuestas, hay una diferencia fundamental que vale la pena señalar, y es cómo se almacena en la memoria. Esto puede tener un efecto importante en el rendimiento de los arreglos. Las estructuras son tipos de valor, por lo que almacenan un valor en el área de memoria a la que apuntan, las clases son tipos de referencia, por lo que hacen referencia a una clase en el área de memoria a la que apuntan, el valor real se almacena en otra parte.

  • Con una estructura, la memoria se asigna dentro de la clase contenedora para almacenar los datos.
  • Con una clase, la clase que contiene solo contendrá un puntero a la nueva clase en un área diferente de la memoria.

Esto también es cierto con las matrices, por lo que una matriz de estructuras se ve así en la memoria.

[struct][struct][struct][struct][struct][struct][struct][struct]

Donde como una serie de clases se ve así

[pointer][pointer][pointer][pointer][pointer][pointer][pointer][pointer]

Los valores reales en los que está interesado no se almacenan realmente en la matriz, sino en otras partes de la memoria.

Para una gran mayoría de aplicaciones, esta diferencia no importa, sin embargo, en el código de alto rendimiento, esto afectará la ubicación de los datos dentro de la memoria y tendrá un gran impacto en el rendimiento de la memoria caché de la CPU. El uso de clases cuando podría / debería haber utilizado estructuras aumentará enormemente el número de fallas de caché en la CPU.

Lo más lento que hace una CPU moderna no es los números precisos, es recuperar datos de la memoria, y un acierto de caché L1 es muchas veces más rápido que leer datos de la RAM.


Un breve resumen de cada uno:

Sólo clases:

  • Puede soportar herencia
  • Son tipos de referencia (puntero)
  • La referencia puede ser nula.
  • Tener sobrecarga de memoria por nueva instancia

Sólo estructuras:

  • No puede soportar la herencia
  • Son tipos de valor
  • Se pasan por valor (como enteros)
  • No se puede tener una referencia nula (a menos que se use Nullable)
  • No tenga una sobrecarga de memoria por cada nueva instancia, a menos que esté 'en caja'

Ambas clases y estructuras:

  • ¿Los tipos de datos compuestos suelen utilizarse para contener algunas variables que tienen alguna relación lógica?
  • Puede contener métodos y eventos.
  • Puede soportar interfaces

Estructura vs clase

Una estructura es un tipo de valor, por lo que se almacena en la pila, pero una clase es un tipo de referencia y se almacena en el montón.

Una estructura no admite herencia y polimorfismo, pero una clase admite ambos.

De forma predeterminada, todos los miembros de la estructura son públicos, pero los miembros de la clase son de naturaleza privada por defecto.

Como una estructura es un tipo de valor, no podemos asignar un valor nulo a un objeto de estructura, pero no es el caso de una clase.







reference-type