2010-05-03 15 views
14

Estoy haciendo el curso 3354 (Implementación de tipos de sistema e interfaces en .NET Framework 2.0) y se dice que para clases simples, con variables y funciones de miembros, es mejor usar una estructura que una clase debido a la sobrecarga."Sobrecarga" de Clase vs Estructura en C#?

Nunca he oído hablar de tal cosa, ¿cuál es la validez de este reclamo?

Respuesta

12

recomiendo a nunca utilice una estructura a menos que tenga un caso de uso muy específico en mente y sabe exactamente cómo la estructura se beneficiará del sistema.

Aunque C# estructuras permiten que los miembros, que trabajan un buen poco diferente a las clases (no se puede subtitular, sin despacho virtual, puede vivir enteramente en la pila) y el comportamiento cambia dependiendo de elevación, etc (Levantar es el proceso de promover un tipo de valor al montón: sorpresa!)

Entonces, para responder a la pregunta: Creo que uno de los mayores nombres incorrectos en C# es el uso de estructuras "para el rendimiento". La razón de esto es que 'gastos generales' no pueden medirse realmente sin ver cómo interactúa con el resto del sistema y el rol, si es que tiene algo de importancia, que juega. Esto requiere un perfil y no se puede resumir con una declaración tan trivial como "menos gastos generales".

Hay buenos casos para los tipos de valores struct - un ejemplo es un valor RGB compuesto almacenado en una matriz para una imagen. Esto se debe a que el tipo RGB es pequeño, no puede haber muy muchos en una imagen, tipos de valores pueden ser embalados bien en las matrices, y pueden ayudar a mantener una mejor localidad de memoria, etc.

+0

Supongo que quiere decir que nunca ha definido una estructura. Probablemente los uses todos los días sin pensarlo. – Gabe

+0

@Gabe Correcto, lo arreglé :-) –

+0

@pst: Creo que Gabe se refiere a donde dices "Recomiendo que nunca uses una estructura". Obviamente, esto no es lo que quieres decir. –

0

struct es un tipo de valor y la clase es de referencia. esta podría ser una de las razones.

1

En C#, las clases y las estructuras son bestias completamente diferentes. La sintaxis es casi idéntica para los dos, pero el comportamiento es completamente diferente (referencia vs. valor). Una instancia individual de una estructura usará menos memoria que la clase equivalente, pero una vez que comience a crear colecciones o pasarlas, la semántica del tipo de valor lo matará en términos de rendimiento (y posiblemente consumo de memoria dependiendo de lo que esté haciendo) a menos los datos en la estructura son muy pequeños. No sé cuál es el número difícil, pero estamos hablando del orden de 8 bytes o menos.

También puede doler en términos de facilidad de mantenimiento y legibilidad porque los dos se ven muy similares, pero se comportan de manera diferente.

+0

El tamaño recomendado es menor que 16 bytes. – ChaosPandion

+0

¡Ah, gracias ChaosPandion! –

+0

Fue la falta de soporte de optimizador para los tipos de valor que fue el asesino de rendimiento. Ahora que eso está solucionado (al menos en la arquitectura x86), debe aumentar los 128 bytes antes de que vea problemas de rendimiento. –

-1

No es necesario asignar/desasignar estructuras.

+1

-1: Esto no es cierto en C#. –

+0

@JohnSaunders Quizás tenga alguna referencia para eso? Todo lo que he leído indica que el compilador asigna y desasigna las estructuras por usted. Aún los inicializas, pero eso sería un problema diferente. – Trisped

+0

El compilador puede hacerlo por usted, pero se lleva a cabo. –

0

Para tipos simples donde se tienen muchos de ellos, no requieren herencia, y son buenos candidatos para ser inmutables, las estructuras son una buena opción. Ejemplos de esto son Point, Rectangle, Decimal y DateTime.

Si no tiene muchos, la sobrecarga es irrelevante y no debe tomar en cuenta su decisión. Si alguna vez necesita derivar de ella (o hacer que sea un tipo derivado), tiene que ser una clase. Si el elemento no puede ser inmutable, struct no es un buen candidato porque la mutación de una instancia no cambiará ninguna copia de la misma.

0

Creo que el punto de equilibrio más comúnmente citado es alrededor de 12 bytes de datos en su estructura. Entonces, por ejemplo, 3 enteros. Sin embargo, la diferencia entre el tipo de valor y el tipo de referencia es mucho más fundamental, y usted debe hacer su elección basándose en eso para los tipos con pocos miembros.

Si algo es grande, entonces la clase :)

+0

El optimizador se arregló hace un par de paquetes de servicio, y ahora las estructuras son muy rápidas con 3 o 4 dobles (32 bytes). El nuevo punto de equilibrio es un poco más grande, supongo que 128 bytes. –

2

vas a utilizar una clase alrededor del 95% de las veces. La semántica del tipo de valor termina mordiéndote por el culo con frecuencia.

Sin embargo, si vas con una estructura, asegúrate de que sea inmutable.

+3

¿Utiliza estructuras el 5% de las veces? : p – Pedery

8

Cuando C# estaba en beta, recibí una demostración de la diferencia entre clase y estructura. Los desarrolladores habían creado un visor de conjuntos de Mandelbrot, que mezcla una gran cantidad de números complejos para lograr su resultado. En la primera instancia, ejecutaron el código con números complejos representados como una clase con un campo Real e Imaginario. Luego, cambiaron la palabra class a struct y volvieron a compilarla. La diferencia en el rendimiento fue enorme.

No tener que asignar objetos de montón ni tener que recogerlos en la basura, en este escenario, fue lo que marcó la diferencia. Según la cantidad de objetos que tenga, la diferencia puede ser más o menos espectacular. Antes de comenzar a ajustar, mida su rendimiento y solo luego tome la decisión de ir con el tipo de valor.

9

En general, no debe cambiar un tipo que debería ser una clase en una estructura por motivos de rendimiento. Las estructuras y las clases tienen una semántica diferente y no son exactamente intercambiables. Es cierto que las estructuras a veces pueden ser más rápidas, pero a veces también pueden ser más lentas. Se comportan de manera diferente y debes reconocer cuándo usar uno u otro.

MSDN tiene una página en choosing between classes and structures.

El resumen es:

no definen una estructura menos que el tipo tiene todas las siguientes características:

  • Es lógicamente representa un único valor, similar a los tipos primitivos (entero, doble, etc.).
  • Tiene un tamaño de instancia inferior a 16 bytes.
  • Es inmutable.
  • No tendrá que estar en la caja con frecuencia.

en ocasiones puede ser un caso en el que un tipo realmente debe ser una clase, pero se necesita que sea una estructura por razones de rendimiento. Esto es raro y debe asegurarse de saber lo que está haciendo antes de tomar esta ruta. Puede ser especialmente peligroso si rompe la guía de inmutabilidad para las estructuras. Las estructuras mutables pueden comportarse de manera que la mayoría de los programadores no esperan.

+5

Y ahora que el optimizador admite inlinear los accesos de estructura (al menos en x86), el límite de tamaño de 16 bytes ya no es apropiado. En algún lugar alrededor de 128 bytes es probablemente un buen límite superior nuevo. –

0

Las estructuras son tipos de valores y las clases son tipos de referencia. Por lo tanto, si va a pasar referencias, las clases pueden ser mejores en cuanto a rendimiento ya que está copiando una dirección en lugar de toda la estructura. Sin embargo, si va a instanciar y hacer referencia a estos objetos una gran cantidad de veces, las estructuras tendrán un rendimiento mucho mejor porque se asignan en la pila. Por lo tanto, las estructuras pueden ser mejores para numerosos objetos donde el rendimiento es importante o en objetos pequeños donde la semántica de tipo de valor es deseable. Las estructuras tampoco tienen un constructor predeterminado. Ellos heredan de Object, pero de lo contrario son libres de herencia.

1

Una regla general se puede seguir es preguntarse si es o no lo que está tratando de hacer es como System.Date Si es no, entonces usted debe realmente cuestionar su decisión de utilizar estructuras.