389 Stimmen

Warum brauchen wir Boxing und Unboxing in C#?

Warum brauchen wir Boxing und Unboxing in C#?

Ich weiß, was Boxen und Unboxing ist, aber ich kann den wirklichen Nutzen nicht begreifen. Warum und wo sollte ich es verwenden?

short s = 25;

object objshort = s;  //Boxing

short anothershort = (short)objshort;  //Unboxing

8voto

BFree Punkte 100035

Das letzte Mal, dass ich etwas entpacken musste, war beim Schreiben von Code, der Daten aus einer Datenbank abruft (ich benutzte keine LINQ to SQL , einfach nur alt ADO.NET ):

int myIntValue = (int)reader["MyIntValue"];

Wenn Sie mit älteren APIs vor den Generika arbeiten, werden Sie auf Boxing stoßen. Ansonsten ist es nicht so häufig.

3voto

Manoj Punkte 39

Boxing ist erforderlich, wenn wir eine Funktion haben, die ein Objekt als Parameter benötigt, aber wir haben verschiedene Werttypen, die übergeben werden müssen, in diesem Fall müssen wir zuerst Werttypen in Objektdatentypen konvertieren, bevor wir sie an die Funktion übergeben.

Ich glaube nicht, dass das stimmt, versuchen Sie stattdessen dies:

class Program
    {
        static void Main(string[] args)
        {
            int x = 4;
            test(x);
        }

        static void test(object o)
        {
            Console.WriteLine(o.ToString());
        }
    }

Das klappt prima, ich habe kein Boxing/Unboxing verwendet. (Es sei denn, der Compiler tut das hinter den Kulissen?)

2voto

supercat Punkte 72939

In .net enthält jede Instanz von Object oder eines davon abgeleiteten Typs eine Datenstruktur, die Informationen über ihren Typ enthält. "Echte" Werttypen in .net enthalten keine derartigen Informationen. Damit Daten in Werttypen von Routinen manipuliert werden können, die von Object abgeleitete Typen erwarten, definiert das System automatisch für jeden Werttyp einen entsprechenden Klassentyp mit denselben Mitgliedern und Feldern. Beim Boxing wird eine neue Instanz dieser Klassenart erzeugt, wobei die Felder aus einer Wertartinstanz kopiert werden. Unboxing kopiert die Felder aus einer Instanz der Klassenart in eine Instanz der Wertart. Alle Klassentypen, die aus Werttypen erzeugt werden, sind von der ironischerweise so benannten Klasse ValueType abgeleitet (die trotz ihres Namens eigentlich ein Referenztyp ist).

1voto

Lewis Kelsey Punkte 3199

Boxing ist die Umwandlung eines Wertes in einen Referenztyp, wobei die Daten an einem bestimmten Offset in einem Objekt auf dem Heap liegen.

Was die eigentliche Aufgabe des Boxens betrifft. Hier sind einige Beispiele

Mono C++

void* mono_object_unbox (MonoObject *obj)
 {    
MONO_EXTERNAL_ONLY_GC_UNSAFE (void*, mono_object_unbox_internal (obj));
 }

#define MONO_EXTERNAL_ONLY_GC_UNSAFE(t, expr) \
    t result;       \
    MONO_ENTER_GC_UNSAFE;   \
    result = expr;      \
    MONO_EXIT_GC_UNSAFE;    \
    return result;

static inline gpointer
mono_object_unbox_internal (MonoObject *obj)
{
    /* add assert for valuetypes? */
    g_assert (m_class_is_valuetype (mono_object_class (obj)));
    return mono_object_get_data (obj);
}

static inline gpointer
mono_object_get_data (MonoObject *o)
{
    return (guint8*)o + MONO_ABI_SIZEOF (MonoObject);
}

#define MONO_ABI_SIZEOF(type) (MONO_STRUCT_SIZE (type))
#define MONO_STRUCT_SIZE(struct) MONO_SIZEOF_ ## struct
#define MONO_SIZEOF_MonoObject (2 * MONO_SIZEOF_gpointer)

typedef struct {
    MonoVTable *vtable;
    MonoThreadsSync *synchronisation;
} MonoObject;

Das Unboxing eines Objekts in Mono ist ein Prozess des Castings eines Zeigers mit einem Offset von 2 gpointers im Objekt (z.B. 16 Bytes). A gpointer es un void* . Dies macht Sinn, wenn man sich die Definition von MonoObject da es sich eindeutig nur um eine Kopfzeile für die Daten handelt.

C++

Um einen Wert in C++ zu boxen, könnten Sie etwas wie folgt tun:

#include <iostream>
#define Object void*

template<class T> Object box(T j){
  return new T(j);
}

template<class T> T unbox(Object j){
  T temp = *(T*)j;
  delete j;
  return temp;
}

int main() {
  int j=2;
  Object o = box(j);
  int k = unbox<int>(o);
  std::cout << k;
}

0voto

Oded Punkte 475566

Wenn eine Methode nur einen Referenztyp als Parameter annimmt (z. B. eine generische Methode, die über die Option new constraint), können Sie ihm keinen Referenztyp übergeben und müssen ihn boxen.

Dies gilt auch für alle Methoden, die object als Parameter angeben - dies wird haben ein Referenztyp sein.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X