Haben Schnittstellenvariablen eine Werttyp- oder Referenztyp-Semantik?
Schnittstellen werden nach Typen implementiert, und diese Typen sind entweder Werttypen oder Referenztypen. Offensichtlich implementieren sowohl int
als auch string
IComparable
, und int
ist ein Werttyp, und string
ist ein Referenztyp. Aber was ist damit:
(Die Frage, die ich beantworten wollte, wurde vermutlich gelöscht, weil gefragt wurde, ob Interfaces auf dem Stack oder dem Heap gespeichert sind. Wie wir alle wissen sollten, ist es konstruktiver, Unterschiede zwischen Value- und Reference-Typen zu berücksichtigen Begriffe für ihre Semantik und nicht für ihre Umsetzung. Für eine Diskussion, siehe Eric Lipperts Der Stack ist ein Implementierungsdetail .)
Normalerweise ist es gemäß den vorhandenen Antworten ein Referenztyp und erfordert Boxen; Es gibt jedoch eine Ausnahme (nicht immer?). In einer generischen Methode mit einer where
-Einschränkung kann beide sein:
Dies ist eine eingeschränkte -Operation, die nicht in eingerahmt ist, auch wenn ein Werttyp ist. Dies wird über constrained
erreicht. Stattdessen führt der JIT die Operation als virtueller Aufruf für Referenztypen und als statischen Aufruf für Werttypen aus. Kein Boxen.
Hier geht es darum zu verstehen, Boxen und Unboxing von Typen. In Ihrem Beispiel wird der Int bei der Zuweisung eingerahmt, und ein Verweis auf dieses "Feld" oder Objekt ist das, was x zugewiesen ist. Der Werttyp int ist als eine Struktur definiert, die IComparable implementiert. Sobald Sie jedoch diese Schnittstellenreferenz verwenden, um auf den Werttyp int zu verweisen, wird sie in einem Rahmen platziert und auf dem Heap platziert. So funktioniert es in der Praxis. Die Tatsache, dass die Verwendung einer Schnittstellenreferenz das definitive Boxen per Definition zur Folge hat, macht diese Referenztyp-Semantik.
Eine Variable oder ein Feld vom Typ IComparable
ist unabhängig vom Typ des diesem Feld zugewiesenen Werts eine Variable oder ein Feld vom Referenztyp. Dies bedeutet, dass x
im Beispielcode eingerahmt ist.
Ein einfacher Test wird das demonstrieren. Der Test basiert auf der Tatsache, dass Sie nur einen Werttyp auf seinen ursprünglichen Typ (und die Nullable-Version dieses Typs) aufheben können :
%Vor%BEARBEITEN
Darüber hinaus definiert die C # -Spezifikation reference-type ausdrücklich als Klassen-, Schnittstellentypen, Array-Typen und Delegattypen.
BEARBEITEN 2
Wie Marc Gravell in seiner Antwort betont, ist ein generischer Typ mit einer Schnittstellenbeschränkung ein anderer Fall. Dies bewirkt nicht Boxen.
Variablen des Interface-Typs haben immer entweder unveränderliche Semantik, veränderbare Referenzsemantik oder "Oddball" -Semantik (etwas anderes als normale Referenz- oder Wertesemantik). Wenn variable1
und variable2
beide als derselbe Schnittstellentyp deklariert sind, führt einer variable2 = variable1
aus, und einer schreibt nie wieder in eine Variable, die Instanz, auf die sich variable1
bezieht, wird immer nicht von der einen unterschieden variable2
(da es dieselbe Instanz ist).
Generische Typen mit Schnittstellenbeschränkungen können eine unveränderliche Semantik, eine veränderbare Referenzsemantik oder eine "skurrile" Semantik aufweisen, können jedoch auch eine Semantik veränderbarer Werte aufweisen. Dies kann gefährlich sein, wenn die Schnittstelle nicht als änderbare Wertesemantik dokumentiert ist. Leider gibt es keine Möglichkeit, eine Schnittstelle so zu beschränken, dass sie entweder eine unveränderliche Semantik oder eine Semantik mit änderbarem Wert hat (dh nach variable2 = variable1
sollte es nicht möglich sein, variable1
zu ändern, indem variable2
geschrieben wird, und umgekehrt). Man könnte eine "struct" -Beschränkung zusammen mit der Schnittstellenbeschränkung hinzufügen, aber das würde Klassen ausschließen, die eine unveränderliche Semantik haben, während Strukturen mit Bezugssemantik nicht ausgeschlossen sind.
Tags und Links .net c# interface value-type reference-type