Kovarianz und Kontravarianz für das gleiche Argument

8

Die C # -Spezifikation besagt, dass ein Argumenttyp nicht gleichzeitig sowohl kovariant als auch kontravariant sein kann.

Dies ist offensichtlich, wenn Sie eine kovariante oder kontravariante Schnittstelle erstellen, dekorieren Sie Ihre Typparameter mit "out" bzw. "in". Es gibt keine Option, die beide gleichzeitig erlaubt ("out").

Ist diese Beschränkung einfach eine sprachspezifische Einschränkung oder gibt es tiefere, fundamentalere Gründe, die in der Kategorientheorie begründet sind, die dazu führen, dass Sie nicht möchten, dass Ihr Typ sowohl kovariant als auch kontravariant ist?

Bearbeiten:

Mein Verständnis war, dass Arrays sowohl kovariant als auch kontravariant waren.

%Vor%     
William Edmondson 24.12.2010, 20:22
quelle

5 Antworten

21

Wie andere bereits gesagt haben, ist es logisch inkonsistent, dass ein generischer Typ sowohl kovariant als auch kontravariant ist. Es gibt hier einige ausgezeichnete Antworten, aber lassen Sie mich zwei weitere hinzufügen.

Lesen Sie zuerst meinen Artikel zum Thema Varianz "Gültigkeit":

Ссылка

Wenn ein Typ "kovariant gültig" ist, dann ist er nicht in einer kontravarianten Weise verwendbar . Wenn es "gegensätzlich gültig" ist, dann ist es nicht in einer kovarianten Weise verwendbar . Etwas, das beide kovariant gültig und gegensätzlich gültig ist, ist weder kovariant noch kontravariant verwendbar . Das heißt, es ist invariant . Also, ist die Vereinigung von kovariant und contravariant: ihre Vereinigung ist invariant .

Zweitens, lassen Sie uns für einen Moment annehmen, dass Sie Ihren Wunsch hatten und dass es eine Typ-Anmerkung gab, die so funktioniert, wie ich denke, dass Sie wollen:

%Vor%

Angenommen, Sie haben IBurger<string> . Da es kovariant ist, ist das in IBurger<object> konvertierbar. Da es kontravariant ist, ist das wiederum in IBurger<Exception> umwandelbar, obwohl "string" und "Exception" überhaupt nichts gemeinsam haben. Grundsätzlich bedeutet "ein und aus", dass IBurger<T1> für alle zwei Referenztypen T1 und T2 in any Typ IBurger<T2> konvertierbar ist. Wie ist das nützlich? Was würden Sie mit einer solchen Funktion machen? Angenommen, Sie haben IBurger<Exception> , aber das Objekt ist tatsächlich ein IBurger<string> . Was können Sie damit tun, dass beide die Tatsache ausnutzen, dass das Argument type Exception ist, und dass dieses Argument type eine komplette Lüge ist, weil das Argument vom Typ "real" ein völlig unzusammenhängender Typ ist?

Um Ihre Folgefrage zu beantworten: Konvertierungen impliziter Referenztypen mit Arrays sind kovariant ; Sie sind nicht kontravariant. Können Sie erklären, warum Sie fälschlicherweise glauben, dass sie kontravariant sind?

    
Eric Lippert 25.12.2010, 01:42
quelle
8

Kovarianz und Kontravarianz schließen sich gegenseitig aus. Ihre Frage ist wie die Frage, ob Menge A sowohl eine Obermenge von Menge B als auch eine Teilmenge von Menge B sein kann. Damit Menge A sowohl eine Teilmenge als auch Obermenge von Menge B ist, muss Menge A gleich Menge B sein, also dann Sie würden einfach fragen, ob die Menge A gleich der Menge B ist.

Mit anderen Worten, nach Kovarianz und Kontravarianz am selben Argument zu fragen, ist wie die Forderung nach überhaupt keiner Varianz (Invarianz), was der Standardwert ist. Daher ist es nicht erforderlich, ein Schlüsselwort anzugeben.

    
Gabe 24.12.2010 20:35
quelle
5

Kovarianz ist für Typen möglich, die Sie nie eingeben (z. B. Memberfunktionen können sie als Rückgabetyp oder out -Parameter verwenden, aber niemals als Eingabeparameter). Kontravarianz ist für Typen möglich, die nie ausgegeben werden (z. B. als Eingabeparameter, aber niemals als Rückgabetyp oder out -Parameter).

Wenn Sie einen Typparameter sowohl kovariant als auch contravariant gemacht haben, konnten Sie ihn nicht eingeben und Sie konnten ihn nicht ausgeben - Sie konnten ihn gar nicht benutzen.

    
Ben Voigt 24.12.2010 20:36
quelle
1

Ohne out und in Keywords Argument ist Covariance und Kontravarianz nicht wahr?

in bedeutet, dass das Argument nur als Funktionsargumenttyp verwendet werden kann

out bedeutet, dass das Argument nur als Rückgabewerttyp

verwendet werden kann

ohne in und out bedeutet, dass es als Argumenttyp und als Rückgabewerttyp

verwendet werden kann     
Arsen Mkrtchyan 24.12.2010 20:31
quelle
0
  

Ist diese Beschränkung einfach eine sprachspezifische Einschränkung oder gibt es tiefere, fundamentalere Gründe, die in der Kategorientheorie begründet sind, die dazu führen, dass Sie nicht möchten, dass Ihr Typ sowohl kovariant als auch kontravariant ist?

Nein, es gibt einen viel einfacheren Grund, der auf der Basislogik (oder einfach dem gesunden Menschenverstand, was immer Sie bevorzugen) basiert: Eine Aussage kann nicht gleichzeitig wahr und nicht wahr sein.

Kovarianz bedeutet S <: T ⇒ G<S> <: G<T> und Kontravarianz bedeutet S <: T ⇒ G<T> <: G<S> . Es sollte ziemlich offensichtlich sein, dass diese zur gleichen Zeit niemals wahr sein können.

    
Jörg W Mittag 25.12.2010 00:15
quelle