Grundlegendes zu C#-Kovarianz und -Kontravarianz (8) Struct und Void

Grundlegendes zu C#-Kovarianz und -Kontravarianz (8) Struct und Void

Grundlegendes zu C#-Kovarianz und -Konreavarianz:

  • Grundlegendes zu C#-Kovarianz und -Kontravarianz (1) Delegaten
  • Grundlegendes zu C#-Schnittstellen für Kovarianz und Kontravarianz (2)
  • C#-Beispiele für Kovarianz und Kontravarianz (3) verstehen
  • Grundlegendes zu C#-Kovarianz- und -Kontravarianz-(4)-Arrays
  • Verstehen von C#-Kovarianz und -Kontravarianz (5) Funktionen höherer Ordnung
  • Verstehen von C#-Kovarianz und -Kontravarianz (6) bei Eingabeproblemen
  • Grundlegendes zu C#-Kovarianz und -Kontravarianz (7) CLR
  • Verstehen von C#-Kovarianz und -Kontravarianz (8) Struct und Void

In Teil 1 wurde erwähnt, dass Varianzen mit struct und void nicht funktionieren.

Struktur

Wenn wir sagen, dass ein abgeleitetes Objekt „ein“ Basisobjekt ist, bedeutet dies, dass die Referenz auf ein abgeleitetes Objekt als Referenz auf ein Basisobjekt betrachtet werden kann.

Aber struct ist ein Werttyp. Wenn auf der von CLI beschriebenen virtuellen Maschine ein Strukturwert an eine Methode übergeben wird, die einen Strukturparameter empfängt, wird dieser Wert kopiert und auf den Stack übertragen. Wenn ein Strukturwert von einer Methode zurückgegeben wird, wird dieses Element auf dem Stapel abgelegt. Wir arbeiten nicht mit Referenzen.

Nichtig

Das Szenario der Leere sieht besonders aus. Auf Microsoft Connect. Jemand fragt nach „Kovariante Rückgabetypen sollten void –> irgendetwas enthalten“.

Es sieht so aus, als ob alles kovariant zu void sein kann:

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(); } }

Es gibt auch einige Leute, die nach dem Parameter fragen:

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());
    }
}

Die beiden obigen Abweichungscodes können nicht in C# 2.0/3.0/4.0 kompiliert werden. Der Grund dafür ist, dass auf der von CLI beschriebenen virtuellen Maschine Funktionen mit Rückgabewert und Funktionen ohne Rückgabewert unterschiedlich funktionieren. Wenn die Variante erlaubt ist, laut Eric Lippert: