In .Net:
Oft können Sie sich nicht darauf verlassen, welchen Variablentyp eine Funktion verbraucht. Daher müssen Sie eine Objektvariable verwenden, die sich vom kleinsten gemeinsamen Nenner aus erstreckt - in .Net ist dies object
.
Ist object
jedoch eine Klasse und speichert ihren Inhalt als Referenz.
List<int> notBoxed = new List<int> { 1, 2, 3 };
int i = notBoxed[1]; // this is the actual value
List<object> boxed = new List<object> { 1, 2, 3 };
int j = (int) boxed[1]; // this is an object that can be 'unboxed' to an int
Während beide die gleichen Informationen enthalten, ist die zweite Liste größer und langsamer. Jeder Wert in der zweiten Liste ist tatsächlich eine Referenz auf einen object
, der die enthält int
.
Dies wird als Box bezeichnet, da das int
von der umwickelt wird object
. Wenn es zurückgeworfen wird, wird das nicht int
verpackt - wieder in seinen Wert konvertiert.
Für Werttypen (dh alle structs
) ist dies langsam und benötigt möglicherweise viel mehr Speicherplatz.
Für Referenztypen (dh alle classes
) ist dies weitaus weniger problematisch, da sie ohnehin als Referenz gespeichert werden.
Ein weiteres Problem mit einem Boxed-Value-Typ ist, dass es nicht offensichtlich ist, dass Sie sich mit der Box und nicht mit dem Wert befassen. Wenn Sie zwei vergleichen, vergleichen structs
Sie Werte, aber wenn Sie zwei vergleichen, vergleichen Sie classes
(standardmäßig) die Referenz - dh handelt es sich um dieselbe Instanz?
Dies kann beim Umgang mit Boxed-Value-Typen verwirrend sein:
int a = 7;
int b = 7;
if(a == b) // Evaluates to true, because a and b have the same value
object c = (object) 7;
object d = (object) 7;
if(c == d) // Evaluates to false, because c and d are different instances
Es ist einfach zu umgehen:
if(c.Equals(d)) // Evaluates to true because it calls the underlying int's equals
if(((int) c) == ((int) d)) // Evaluates to true once the values are cast
Es ist jedoch eine andere Sache, auf die Sie beim Umgang mit Boxwerten achten müssen.