Comprender la covarianza y la contravarianza de C# (8) Estructura y vacío

Comprender la covarianza y la contravarianza de C# (8) Estructura y vacío

Comprender la covarianza y la conreavarianza de C#:

  • Comprensión de los delegados de covarianza y contravarianza de C# (1)
  • Comprensión de las interfaces de covarianza y contravarianza de C# (2)
  • Comprensión de las muestras de covarianza y contravarianza de C# (3)
  • Comprensión de las matrices de covarianza y contravarianza de C# (4)
  • Comprensión de las funciones de orden superior de covarianza y contravarianza de C# (5)
  • Comprensión de la covarianza y la contravarianza de C# (6) Problemas de tipeo
  • Comprensión de la covarianza y la contravarianza de C# (7) CLR
  • Comprensión de la covarianza y la contravarianza de C# (8) Struct and Void

La Parte 1 mencionó que las variaciones no funcionan con struct y void.

Estructura

Cuando decimos que el objeto Derivado "es un" objeto Base, significa que la referencia a un objeto Derivado puede considerarse como una referencia a un objeto Base.

Pero la estructura es un tipo de valor. En la máquina virtual descrita por CLI, al pasar un valor de estructura a un método que recibe el parámetro de estructura, ese valor se copia y se envía a la pila. Al devolver un valor de estructura de un método, ese elemento se coloca en la pila. No estamos trabajando con referencias.

Vacío

El escenario del vacío se ve especial. En Microsoft Connect. Alguien está preguntando por "Los tipos de devolución covariante deben incluir void -> cualquier cosa".

Parece que cualquier cosa puede ser covariante de void:

internal delegate void VoidOut();

internal delegate object ObjectOut();

internal class Program
{
    private static void Main()
    {
        VoidOut voidOut = () => { };
        ObjectOut objectOut = () => new object();

        // It looks like covariance is Ok here.
        voidOut = objectOut;

        // Because when we invoke [void voidOut()], we are invoking [object objectOut()]. 
// The return value of [object objectOut()] can be just ignored. voidOut(); } }

También hay algunas personas que preguntan sobre el parámetro:

internal delegate void NoParameterIn();

internal delegate void ObjectIn(object @object);

internal class Program
{
    private static void Main()
    {
        NoParameterIn noParameterIn = () => { };
        ObjectIn objectIn = (@object) => { };

        // It looks like contravariance is Ok here.
        objectIn = noParameterIn;

        // Because when we invoke [void objectIn(object)], we are invoking [void noParameterIn()].
        // The parameter of [void objectIn(object)] can be just ignored.
        objectIn(new object());
    }
}

Los dos códigos de variación anteriores no se pueden compilar en C# 2.0/3.0/4.0. El motivo es que, en la máquina virtual descrita por CLI, la función con valor devuelto y la función sin valor devuelto funcionan de manera diferente. Si la variante está permitida, según Eric Lippert: