que pertenece marcador lista etiqueta elemento definicion body atributos adónde .net struct clr value-type reference-type

.net - pertenece - ¿Tiene sentido definir una estructura con un miembro de tipo de referencia?



tags en html (4)

¿Tiene sentido definir una estructura con un miembro de tipo de referencia (y no definirla como una clase)? Por ejemplo, para definir esta estructura:

public struct SomeStruct { string name; Int32 place; }

Lo pregunto porque sé que una estructura es un tipo de valor, y definir en ella algún tipo de referencia no tiene ningún sentido.

Estoy en lo cierto ¿Alguien puede explicar esto?


Declarar un campo de un tipo de referencia significa que debe haber espacio para mantener el valor de la referencia que apunta al objeto de destino. Por lo tanto, tiene mucho sentido tener tales campos en las estructuras.


En general, una estructura solo debe contener un campo público y / o mutable de un tipo de referencia si se cumple alguna de las siguientes condiciones:

  1. Todas las instancias de ese tipo pueden considerarse como inherentemente inmutables (como es el caso de `string`)
  2. La semántica de la estructura implica claramente que el campo identifica el objeto al que se refiere, en lugar de encapsular su estado, y que el estado del objeto al que hace referencia el campo no se considera parte de la estructura. Por ejemplo, en un KeyValuePair <string, Form>, uno esperaría que el `Valor` identifique una instancia de formulario; mover el formulario alrededor de la pantalla cambiaría `Value.Bounds`, pero no se consideraría que cambie` Value` (que continuaría haciendo referencia al mismo formulario, independientemente de su ubicación en pantalla)

Si ninguna de las dos condiciones se aplica, puede ser apropiado que una estructura contenga un campo de un tipo de referencia siempre que se apliquen todas las condiciones siguientes:

  1. El campo nunca contiene una referencia a ningún objeto mutable que la estructura no haya creado.
  2. La referencia nunca debe estar expuesta, ni nunca debe haber estado expuesta, a ningún código que pueda en el futuro mutar el objeto al que se refiere.
  3. Todas las mutaciones que se van a realizar en el objeto al que se va a referir el campo deben realizarse antes de que se almacene una referencia en el campo.

En otras palabras, una referencia de objeto que se usa para encapsular el estado de un objeto (en lugar de simplemente identificarlo) solo debe almacenarse en un campo de estructura si no hay una ruta de ejecución a través de la cual se pueda modificar el objeto al que se refiere. .


Estoy interesado en escuchar lo que los programadores más experimentados tienen que decir sobre las ventajas y desventajas de esto, pero entiendo que, como tipo de valor, una variable de tipo SomeStruct se asignaría de la pila, pero contendría una referencia a la ubicación en el montón que contiene la cadena.


Nueve veces de cada diez, debería estar creando una clase en lugar de una estructura en primer lugar. Las estructuras y las clases tienen una semántica muy diferente en C #, en comparación con lo que puedes encontrar en C ++, por ejemplo. La mayoría de los programadores que usan una estructura deberían haber usado una clase, haciendo preguntas como esta francamente irrelevantes.

Aquí hay algunas reglas rápidas acerca de cuándo debe elegir una estructura sobre una clase:

  1. Nunca.
    ... Oh, ¿sigues leyendo? Eres persistente Bien vale.
  2. Cuando tiene una necesidad explícita de semántica de tipo valor, a diferencia de la semántica de tipo de referencia.
  3. Cuando tiene un tipo muy pequeño (la regla de oro es una huella de memoria de menos de 16 bytes).
  4. Cuando los objetos representados por su estructura serán de corta duración e inmutables (no cambiarán).
  5. Y ocasionalmente, para fines de interoperabilidad con código nativo que utiliza estructuras.

Pero si ha tomado una decisión informada y está realmente seguro de que la necesita, de hecho, necesita una estructura en lugar de una clase, debe revisar el punto número 2 y comprender qué tipo de valor es la semántica. El artículo de Jon Skeet aquí debería hacer mucho para aclarar la distinción.

Una vez que haya hecho eso, debe comprender por qué la definición de un tipo de referencia dentro de un tipo de valor (estructura) no es un problema. Los tipos de referencia son como punteros. El campo dentro de la estructura no almacena el tipo real; más bien, almacena un puntero (o una referencia) a ese tipo. No hay nada contradictorio o incorrecto en declarar una estructura con un campo que contiene un tipo de referencia. Ni "ralentizará el objeto" ni "llamará a GC", las dos preocupaciones que expresas en un comentario.