2009-03-20 17 views
7

MSDN dice que una clase que sería de 16 bytes o menos se manejaría mejor como struct [citation].
¿Por qué es eso?
¿Eso significa que si una estructura tiene más de 16 bytes es menos eficiente que una clase o es la misma?
¿Cómo se determina si su clase tiene menos de 16 bytes?
¿Qué restringe una estructura de actuar como una clase? (además de no permitir constructores sin parámetros)Preguntas sobre Structs

+0

Puede encontrar mucha información sobre las estructuras de C# aquí: http://stackoverflow.com/questions/85553/when-should-i-use-a-struct-instead-of-a-class –

+0

Tiene probablemente ya lo haya encontrado, pero hay mucho más en MSDN, aquí: http://msdn.microsoft.com/en-us/library/ms229017.aspx –

+0

Acabo de encontrar ese _right_ antes de publicarlo. ¡Gracias! – Malfist

Respuesta

6

Hay un par de diferentes respuestas a esta pregunta, y es un poco subjetivo, pero algunas de las razones que se me ocurren son:

  • las estructuras son de tipo valor, las clases son de tipo de referencia. Si está utilizando 16 bytes para el almacenamiento total, probablemente no valga la pena crear referencias de memoria (de 4 a 8 bytes) para cada uno.
  • Cuando tiene objetos realmente pequeños, a menudo pueden insertarse en la pila IL, en lugar de referencias a los objetos. Esto realmente puede acelerar un poco el código, ya que está eliminando una referencia de memoria en el lado del destinatario.
  • Hay un poco de "pelusa" adicional asociada con las clases en IL, y si su estructura de datos es muy pequeña, ninguna de estas pelusas se usaría de todos modos, por lo que es basura extra que no necesita.

La diferencia más importante entre una estructura y una clase, sin embargo, es que las estructuras son de tipo de valor y las clases son de tipo de referencia.

+0

¡Oh! lo siento, debería haber escrito "Intermediate Language", que es una especie de abreviatura para todo el "CLR", Common Language Runtime: es la máquina virtual que ejecuta el código .NET. – Mike

+0

Bien, como la JVM? – Malfist

+0

Creo que IL ~ java bytecode, y CLR ~ JVM – eglasius

0

En la memoria, la estructura contendrá los datos directamente, mientras que una clase se comportará más como un puntero. Eso solo hace una diferencia importante, ya que pasar la estructura como parámetro a un método pasará sus valores (cópialos en la pila), mientras que la clase pasará la referencia a los valores. Si la estructura es grande, estará copiando muchos valores en cada llamada a método. Cuando es realmente pequeño, copiar los valores y usarlos directamente será probablemente más rápido que copiar el puntero y tener que tomarlos de otro lugar.

Acerca de las restricciones: no se puede asignar a nulo (aunque puede usar Nullable <>) y debe inicializarlo de inmediato.

+0

MSDN dice que Struct se almacena en la pila, mientras que una clase se almacena en el montón. – Malfist

+1

Sí, eso es cierto. Las variables de pila pueden atravesarse más rápido que las variables de pila.Pero cuando pasa una estructura como parámetro a un método, se copiará a la pila por completo antes de llamar al método, mientras que para una clase solo se copiará un puntero. – Groo

2

Revise este enlace, lo encontré en una de las respuestas en SO hoy: .NET Type Internals. También puede intentar buscar SO y buscar en Google "tipos de referencia contra tipos de valores" para las diferencias entre estructuras y clases.

¿Qué impide que una estructura actúe como una clase?

Existen muchas diferencias. No puede heredar de una estructura, por ejemplo.

No puede tener métodos virtuales, por lo que no puede usar una estructura para implementar una interfaz. Los métodos de instancia en las estructuras pueden acceder a los campos privados de struct, pero aparte de eso se comportan de manera muy similar a las funciones auxiliares "auxiliares" (para las estructuras inmutables, a veces ni siquiera necesitan acceder a datos privados). Por lo tanto, considero que no son tan "valiosos" como los métodos de clase.

+0

"no es muy beneficioso agregar métodos de instancia a una estructura" - ¿Puede ampliar esto más? Lo he encontrado muy útil, es decir, agregando un ToString() –

+0

La mayoría de las clases deben estar selladas, pero veo su punto. – Malfist

+0

@Neil: Lo reformulé un poco, disculpe la mala elección de las palabras. – Groo

0

Esto se debe a la forma diferente en que CLR maneja las estructuras y las clases. Las estructuras son tipos de valores, lo que significa que viven en la pila en lugar de en el montón administrado.Es una buena regla general mantener las estructuras pequeñas porque una vez que empiezas a pasarlas como argumentos de método incurrirás en gastos generales ya que las estructuras se copian en su totalidad cuando se pasan a un método.

Dado que las clases pasan una copia de su referencia a los métodos, incurren en mucha menos sobrecarga cuando se usan como argumentos de método.

La mejor manera de determinar el tamaño de su clase es totalizar el número de bytes requeridos por todos los miembros de su clase más 8 bytes adicionales para los elementos generales de CLR (el índice de bloque de sincronización y la referencia al tipo de el objeto).

0

Las estructuras son diferentes de las clases porque se almacenan en la pila y no en el montón. Esto significa que cada vez que llamas a un método con struct como parámetro, se crea una copia y se pasa al método. Es por eso que las estructuras grandes son extremadamente ineficientes.

No obstante, desalentaría activamente el uso de estructuras, ya que podría causar algunos errores sutiles: p. cuando cambia un campo de una estructura, no se reflejará para la persona que llama (porque usted solo cambió la copia), lo cual es un comportamiento completamente diferente de las clases.

Así que los 16 bytes creo que es un tamaño máximo razonable de una estructura, pero aún así en la mayoría de los casos es mejor tener una clase. Si aún desea crear una estructura, intente que sea inmutable al menos.

3

Por "eficiente", probablemente estén hablando de la cantidad de memoria que se necesita para representar la clase o estructura.

En la plataforma de 32 bits, la asignación de un objeto requiere un mínimo de 16 bytes. En una plataforma de 64 bits, el tamaño mínimo del objeto es de 24 bytes. Por lo tanto, si lo está mirando únicamente a partir de la cantidad de memoria utilizada, una estructura que contenga menos de 16 bytes de datos será "mejor" que la clase correspondiente.

Pero la cantidad de memoria utilizada no es toda la historia. Los tipos de valores (estructuras) son fundamentalmente diferentes a los tipos de referencia (clases). Las estructuras pueden ser inconvenientes para trabajar, y en realidad pueden causar problemas de rendimiento si no tienes cuidado.

La respuesta real, por supuesto, es utilizar la que mejor se adapte a su situación. En la mayoría de los casos, será mucho mejor usar clases.

0

Copiar una instancia de una estructura toma menos tiempo que crear una nueva instancia de una clase y copiar datos de una anterior, pero las instancias de clase se pueden compartir y las instancias de estructura no. Por lo tanto, "structvar1 = structvar2" requiere copiar nueva instancia struct, mientras que "classvar1 = classvar2" permite que classvar1 y classvar2 hagan referencia a la misma instancia struct (sin tener que crear una nueva instancia).

El código para manejar la creación de nuevas instancias struct está optimizado para tamaños de hasta 16 bytes. Las estructuras más grandes se manejan de manera menos eficiente. Las estructuras son una ganancia en los casos en que cada variable que contiene una estructura contendrá una instancia independiente (es decir, no hay ninguna razón para esperar que dos variables en particular tengan instancias idénticas); no son una gran ganancia (si es que ganan) en los casos en que muchas variables pueden contener la misma instancia.