Konwersja boxing i konwersja unboxing (Przewodnik programowania w języku C#)
Opakowywanie to proces konwersji typu wartości na typ object lub dowolny typ interfejsu implementowany przez ten typ wartości.Gdy środowisko CLR opakowuje typ wartości, otacza wartość wewnątrz elementu System.Object i zapisuje go w zarządzanej stercie.Rozpakowywanie wyodrębnia typ wartości z obiektu.Opakowywanie jest niejawne; rozpakowywanie jest jawne.Pojęcie pakowania i rozpakowywania podkreśla zunifikowany sposób, w jaki C# postrzega system typów, w którym wartość dowolnego typu może być traktowana jako obiekt.
W poniższym przykładzie zmienna liczba całkowita i jest opakowana i przypisana do obiektu o.
int i = 123;
// The following line boxes i.
object o = i;
Obiekt o następnie może być rozpakowany i przypisany do zmiennej całkowitej i:
o = 123;
i = (int)o; // unboxing
Poniższe przykłady ilustrują, jak pakowanie jest używane w języku C#.
// String.Concat example.
// String.Concat has many versions. Rest the mouse pointer on
// Concat in the following statement to verify that the version
// that is used here takes three object arguments. Both 42 and
// true must be boxed.
Console.WriteLine(String.Concat("Answer", 42, true));
// List example.
// Create a list of objects to hold a heterogeneous collection
// of elements.
List<object> mixedList = new List<object>();
// Add a string element to the list.
mixedList.Add("First Group:");
// Add some integers to the list.
for (int j = 1; j < 5; j++)
{
// Rest the mouse pointer over j to verify that you are adding
// an int to a list of objects. Each element j is boxed when
// you add j to mixedList.
mixedList.Add(j);
}
// Add another string and more integers.
mixedList.Add("Second Group:");
for (int j = 5; j < 10; j++)
{
mixedList.Add(j);
}
// Display the elements in the list. Declare the loop variable by
// using var, so that the compiler assigns its type.
foreach (var item in mixedList)
{
// Rest the mouse pointer over item to verify that the elements
// of mixedList are objects.
Console.WriteLine(item);
}
// The following loop sums the squares of the first group of boxed
// integers in mixedList. The list elements are objects, and cannot
// be multiplied or added to the sum until they are unboxed. The
// unboxing must be done explicitly.
var sum = 0;
for (var j = 1; j < 5; j++)
{
// The following statement causes a compiler error: Operator
// '*' cannot be applied to operands of type 'object' and
// 'object'.
//sum += mixedList[j] * mixedList[j]);
// After the list elements are unboxed, the computation does
// not cause a compiler error.
sum += (int)mixedList[j] * (int)mixedList[j];
}
// The sum displayed is 30, the sum of 1 + 4 + 9 + 16.
Console.WriteLine("Sum: " + sum);
// Output:
// Answer42True
// First Group:
// 1
// 2
// 3
// 4
// Second Group:
// 5
// 6
// 7
// 8
// 9
// Sum: 30
Wydajność
W stosunku do prostych zadań pakowanie i rozpakowywanie są wymagające pod względem mocy obliczeniowej.Gdy typ wartości jest spakowany, należy przydzielić i utworzyć nowy obiekt.W mniejszym stopniu cast wymagany do rozpakowywania również wymaga dużej mocy obliczeniowej.Aby uzyskać więcej informacji, zobacz Wydajność.
Opakowywanie
Opakowywanie służy do przechowywania typów wartości w stosie zebranych elementów bezużytecznych.Opakowywanie to niejawna konwersja typu wartości na typ object lub dowolny typ interfejsu implementowany przez ten typ wartości.Opakowanie typu wartości przydziela wystąpienie obiektu do stosu i kopiuje wartość do nowego obiektu.
Rozważmy następującą deklarację zmiennej o typie wartości:
int i = 123;
Poniższa instrukcja stosuje niejawnie operację pakowania na zmiennej i:
// Boxing copies the value of i into object o.
object o = i;
W wyniku tego instrukcja tworzy odwołanie do obiektu o, na stosie, który odwołuje się do wartości typu int, na stercie.Ta wartość jest kopią wartości typ-wartość przypisanej do zmiennej i.Różnicę między dwiema zmiennymi, i i o, przedstawiono na poniższym rysunku.
Konwersja opakowująca
Jest również możliwe jawne przeprowadzenie pakowania, jak w poniższym przykładzie, ale jawne pakowanie nigdy nie jest wymagane:
int i = 123;
object o = (object)i; // explicit boxing
Opis
Ten przykład konwertuje zmienną całkowitą i na obiekt o za pomocą pakowania.Następnie wartość przechowywana w zmiennej i zostaje zmieniona z 123 na 456.W przykładzie pokazano, że oryginalny typ wartości i spakowany obiekt używają innych lokalizacji pamięci, dlatego mogą przechowywać różne wartości.
Przykład
class TestBoxing
{
static void Main()
{
int i = 123;
// Boxing copies the value of i into object o.
object o = i;
// Change the value of i.
i = 456;
// The change in i does not effect the value stored in o.
System.Console.WriteLine("The value-type value = {0}", i);
System.Console.WriteLine("The object-type value = {0}", o);
}
}
/* Output:
The value-type value = 456
The object-type value = 123
*/
Poniższy przykład ilustruje przypadek nieprawidłowego rozpakowania i wynikający z tego wyjątek InvalidCastException.Gdy wystąpi błąd, za pomocą try i catch jest wyświetlany komunikat o błędzie.
class TestUnboxing
{
static void Main()
{
int i = 123;
object o = i; // implicit boxing
try
{
int j = (short)o; // attempt to unbox
System.Console.WriteLine("Unboxing OK.");
}
catch (System.InvalidCastException e)
{
System.Console.WriteLine("{0} Error: Incorrect unboxing.", e.Message);
}
}
}
Ten program wyświetla:
Specified cast is not valid. Error: Incorrect unboxing.
Jeśli zmienisz instrukcję:
int j = (short) o;
do:
int j = (int) o;
Konwersja zostanie przeprowadzona i otrzymasz dane wyjściowe:
Unboxing OK.
Rozpakowywanie
Rozpakowywanie to konwersja jawna z typu object na typ wartości lub z typu interfejsu na typ wartości, która implementuje interfejs.Operacja rozpakowania składa się z:
Sprawdzanie wystąpienie obiektu, aby upewnić się, że jest zapakowaną wartością danego typu wartości.
Kopiowanie wartości z instancji do zmiennej typu wartości.
Następujące instrukcje pokazują zarówno operacje pakowania, jak i rozpakowania:
int i = 123; // a value type
object o = i; // boxing
int j = (int)o; // unboxing
Następujący rysunek ilustruje wynik poprzednich instrukcji.
Konwersja rozpakowująca
Dla rozpakowywania typów wartości, aby uzyskać sukces w czasie wykonywania, rozpakowywany element musi być odwołaniem do obiektu, który został wcześniej utworzony przez pakowanie instancji tego typu wartości.Próba rozpakowania obiektu null powoduje wyjątek NullReferenceException.Próba rozpakowania odwołania do niezgodnego typu wartości spowoduje wyjątek InvalidCastException.
Specyfikacja języka C#
Aby uzyskać więcej informacji, zobacz Specyfikacja języka C#. Specyfikacja języka jest ostatecznym źródłem informacji o składni i użyciu języka C#.
Sekcje pokrewne
Aby uzyskać więcej informacji:
Specyfikacja języka C#
Aby uzyskać więcej informacji, zobacz Specyfikacja języka C#. Specyfikacja języka jest ostatecznym źródłem informacji o składni i użyciu języka C#.