valor tipos textuales tablas referencias referencia por parametros para datos c# .net interface value-type reference-type

c# - tipos - ¿Las variables de interfaz tienen semántica de tipo de valor o de tipo de referencia?



tipos de datos por valor y referencia (4)

Las variables del tipo de interfaz siempre tendrán semántica inmutable, semántica de referencia mutable o semántica "oddball" (algo que no sea la semántica de referencia o valor normal). Si variable1 y variable2 se declaran como el mismo tipo de interfaz, uno realiza variable2 = variable1 , y uno nunca vuelve a escribir en ninguna de las variables, la instancia a la que hace referencia la variable1 siempre será indistinguible de la que se refiere a la variable2 (ya que será la misma instancia).

Los tipos genéricos con restricciones de interfaz pueden tener semántica inmutable, semántica de referencia mutable o semántica "estrafalaria", pero también pueden tener semántica de valores mutables. Esto puede ser peligroso si la interfaz no está documentada como que tiene semántica de valores mutables. Desafortunadamente, no hay forma de restringir una interfaz para que tenga semántica inmutable o semántica de valores mutables (lo que significa que después de variable2 = variable1 , no debería ser posible cambiar la variable1 escribiendo variable2 , ni viceversa). Se podría agregar una restricción "struct" junto con la restricción de interfaz, pero eso excluiría las clases que tienen semántica inmutable sin excluir las estructuras que tienen semántica de referencia.

¿Las variables de interfaz tienen semántica de tipo de valor o de tipo de referencia?

Las interfaces se implementan por tipos, y esos tipos son tipos de valores o tipos de referencia. Obviamente, tanto int como string implementan IComparable , y int es un tipo de valor, y string es un tipo de referencia. Pero que hay de esto:

IComparable x = 42; IComparable y = "Hello, World!";

(La pregunta que estaba tratando de responder fue presumiblemente eliminada porque preguntaba si las interfaces están almacenadas en la pila o el montón, y, como todos deberíamos saber, es más constructivo pensar en las diferencias entre los tipos de valor y referencia en términos de su semántica en lugar de su implementación. Para una discusión, vea La pila de Eric Lippert es un detalle de implementación .)


Por lo general, según las respuestas existentes, es un tipo de referencia y requiere boxeo; Sin embargo, hay una excepción (¿no hay siempre?). En un método genérico con una restricción where , puede ser ambos :

void Foo<T>(T obj) where T : ISomeInterface { obj.SomeMethod(); }

Esta es una operación restringida , y no está encuadrada incluso si es un tipo de valor. Esto se logra a través de constrained . En cambio, el JIT realiza la operación como llamada virtual para tipos de referencia y llamada estática para tipos de valor. Sin boxeo.


Se trata de entender el boxeo y el desempaquetado de tipos. En su ejemplo, el int está encuadrado en la asignación y una referencia a ese "cuadro" u objeto es lo que se asigna a x. El tipo de valor int se define como una estructura que implementa IComparable. Sin embargo, una vez que use esa referencia de interfaz para referirse al tipo de valor int, se colocará en un recuadro y se colocará en el montón. Así es como funciona en la práctica. El hecho de que el uso de una referencia de interfaz hace que el boxeo ocurra por definición hace que esta semántica de tipo de referencia.

MSDN: Boxeo y Unboxing


Una variable o campo cuyo tipo es IComparable es una variable o campo de tipo referencia, independientemente del tipo del valor asignado a ese campo. Esto significa que x en el código de muestra está encuadrado.

Una simple prueba lo demostrará. La prueba se basa en el hecho de que solo puede desvincular un tipo de valor a su tipo original (y la versión que puede contener nulos de ese tipo) :

[TestMethod, ExpectedException(typeof(InvalidCastException))] public void BoxingTest() { IComparable i = 42; byte b = (byte)i; //exception: not allowed to unbox an int to any type other than int Assert.AreEqual(42, b); Assert.Fail(); }

EDITAR

Además de eso, la especificación C # define específicamente el tipo de referencia que comprende tipos de clase, tipos de interfaz, tipos de matriz y tipos de delegado.

EDIT 2

Como señala Marc Gravell en su respuesta, un tipo genérico con una restricción de interfaz es un caso diferente. Esto no causa el boxeo.