Frage

Ich suche eine klare, prägnante und genaue Antwort.

Idealerweise als eigentliche Antwort, obwohl Links zu guten Erklärungen willkommen sind.

War es hilfreich?

Lösung

Eingerahmte Werte sind Datenstrukturen Das sind nur minimale Wrapper primitive Typen*.Eingerahmte Werte werden normalerweise als Zeiger auf Objekte gespeichert der Haufen.

Daher verbrauchen geschachtelte Werte mehr Speicher und es sind mindestens zwei Speichersuchen erforderlich, um darauf zuzugreifen:einmal, um den Zeiger zu erhalten, und ein weiteres Mal, um diesem Zeiger auf das Grundelement zu folgen.Offensichtlich ist das nicht das, was Sie in Ihren inneren Schleifen wollen.Andererseits funktionieren geschachtelte Werte in der Regel besser mit anderen Typen im System.Da es sich um erstklassige Datenstrukturen in der Sprache handelt, verfügen sie über die erwarteten Metadaten und die erwartete Struktur wie andere Datenstrukturen.

In Java und Haskell können generische Sammlungen keine unverpackten Werte enthalten.Generische Sammlungen in .NET können unverpackte Werte ohne Nachteile enthalten.Während die Generika von Java nur zur Typprüfung zur Kompilierungszeit verwendet werden, wird dies bei .NET der Fall sein Generieren Sie spezifische Klassen für jeden zur Laufzeit instanziierten generischen Typ.

Java und Haskell verfügen über Arrays ohne Box, sind aber deutlich weniger praktisch als die anderen Sammlungen.Wenn jedoch Spitzenleistung erforderlich ist, lohnt es sich, ein wenig Unannehmlichkeiten in Kauf zu nehmen, um den Aufwand für das Ein- und Auspacken zu vermeiden.

* Für diese Diskussion ist ein primitiver Wert jeder Wert, auf dem gespeichert werden kann der Aufrufstapel, anstatt als Zeiger auf einen Wert auf dem Heap gespeichert zu werden.Häufig sind das nur die Maschinentypen (Ints, Floats usw.), Strukturen und manchmal Arrays statischer Größe..NET-land nennt sie Werttypen (im Gegensatz zu Referenztypen).Java-Leute nennen sie primitive Typen.Haskellions nennen sie einfach „unboxed“.

** Ich konzentriere mich in dieser Antwort auch auf Java, Haskell und C#, weil ich das weiß.Python, Ruby und Javascript haben alle ausschließlich geboxte Werte.Dies wird auch als „Alles ist ein Objekt“-Ansatz*** bezeichnet.

*** Vorbehalt:Ein ausreichend fortgeschrittener Compiler/JIT kann in manchen Fällen tatsächlich erkennen, dass ein Wert, der beim Betrachten der Quelle semantisch geboxt ist, zur Laufzeit sicher ein entboxter Wert sein kann.Im Wesentlichen sind Ihre Boxen dank brillanter Sprachimplementierer manchmal kostenlos.

Andere Tipps

aus C# 3.0 auf den Punkt gebracht:

Das Boxen ist der Akt des Werbungsstättens in einen Referenztyp:

int x = 9; 
object o = x; // boxing the int

Auspacken ist...Die Umkehrung:

// unboxing o
object o = 9; 
int x = (int)o; 

Beim Boxen und Unboxing handelt es sich um den Prozess der Konvertierung eines Grundwerts in eine objektorientierte Wrapper-Klasse (Boxing) oder des Konvertierens eines Werts aus einer objektorientierten Wrapper-Klasse zurück in den Grundwert (Unboxing).

In Java müssen Sie beispielsweise möglicherweise eine konvertieren int Wert in einen Integer (Boxen), wenn Sie es in einem aufbewahren möchten Collection weil Grundelemente nicht in a gespeichert werden können Collection, nur Objekte.Aber wenn du es wieder rausholen willst Collection Möglicherweise möchten Sie den Wert als erhalten int und nicht ein Integer Sie würden es also auspacken.

Ein- und Auspacken ist nicht von Natur aus möglich schlecht, aber es ist ein Kompromiss.Abhängig von der Sprachimplementierung kann es langsamer und speicherintensiver sein als nur die Verwendung von Grundelementen.Es ermöglicht Ihnen jedoch möglicherweise auch die Verwendung von Datenstrukturen höherer Ebenen und eine größere Flexibilität in Ihrem Code.

Heutzutage wird es am häufigsten im Zusammenhang mit der „Autoboxing/Autounboxing“-Funktion von Java (und anderen Sprachen) diskutiert.Hier ist ein Java-zentrierte Erklärung von Autoboxing.

In .Net:

Oftmals kann man sich nicht darauf verlassen, welche Art von Variable eine Funktion verbrauchen wird, daher muss man eine Objektvariable verwenden, die vom kleinsten gemeinsamen Nenner ausgeht – in .Net ist dies der Fall object.

Jedoch object ist 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 ein Verweis auf einen object das hält die int.

Dies wird Boxed genannt, weil das int wird von der umhüllt object.Wenn es zurückgeworfen wird int wird ausgepackt und wieder in seinen Wert umgewandelt.

Für Werttypen (d. h.alle structs), das ist langsam und verbraucht möglicherweise viel mehr Platz.

Für Referenztypen (d. h.alle classes) ist dies weitaus weniger problematisch, da sie ohnehin als Referenz gespeichert werden.

Ein weiteres Problem bei einem Box-Werttyp besteht darin, dass nicht offensichtlich ist, dass es sich um die Box und nicht um den Wert handelt.Wenn man zwei vergleicht structs dann vergleicht man Werte, aber wenn man zwei vergleicht classes dann vergleichen Sie (standardmäßig) die Referenz - d. h.Sind das die gleichen Exemplare?

Dies kann beim Umgang mit geschachtelten Werttypen 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 lässt sich ganz einfach 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 gibt jedoch noch eine weitere Sache, auf die Sie beim Umgang mit Werten in Kästchen achten sollten.

Die generischen .NET FCL-Sammlungen:

List<T>
Dictionary<TKey, UValue>
SortedDictionary<TKey, UValue>
Stack<T>
Queue<T>
LinkedList<T>

wurden alle entwickelt, um die Leistungsprobleme beim Ein- und Auspacken in früheren Sammlungsimplementierungen zu überwinden.

Weitere Informationen finden Sie in Kapitel 16, CLR über C# (2. Auflage).

Beim Boxen handelt es sich um den Prozess der Konvertierung eines Werttyps in einen Referenztyp.

Unter Unboxing versteht man die Konvertierung eines Referenztyps in einen Werttyp.

EX: int i=123;
    object o=i;// Boxing
    int j=(int)o;// UnBoxing

Werttyp sind:
int, char und Strukturen, Aufzählungen.Referenztypen sind:Klassen, Schnittstellen, Arrays, Strings und Objekte

Durch das Ein- und Auspacken können Werttypen als Objekte behandelt werden.Boxen bedeutet, einen Wert in eine Instanz des Objektreferenztyps umzuwandeln.Zum Beispiel, Int ist eine Klasse und int ist ein Datentyp.Konvertieren int Zu Int ist ein Beispiel für Boxen, während Konvertieren Int Zu int wird gerade ausgepackt.Das Konzept hilft bei der Garbage Collection, Unboxing hingegen wandelt den Objekttyp in einen Werttyp um.

int i=123;
object o=(object)i; //Boxing

o=123;
i=(int)o; //Unboxing.

Wie alles andere kann Autoboxing problematisch sein, wenn es nicht sorgfältig eingesetzt wird.Der Klassiker besteht darin, am Ende eine NullPointerException zu erhalten und diese nicht aufspüren zu können.Sogar mit einem Debugger.Versuche dies:

public class TestAutoboxNPE
{
    public static void main(String[] args)
    {
        Integer i = null;

        // .. do some other stuff and forget to initialise i

        i = addOne(i);           // Whoa! NPE!
    }

    public static int addOne(int i)
    {
        return i + 1;
    }
}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top