Zabalení a rozbalení (Průvodce programováním v C#)
Balení je proces převodu typu hodnoty na typ object
nebo na jakýkoli typ rozhraní implementovaný tímto typem hodnoty. Když modul CLR (Common Language Runtime) zadá typ hodnoty, zabalí hodnotu do System.Object instance a uloží ji do spravované haldy. Rozbalení extrahuje typ hodnoty z objektu . Boxování je implicitní; příkaz unboxing je explicitní. Koncept balení a rozbalování je základem jednotného zobrazení C# systému typů, ve kterém lze zacházet s hodnotou libovolného typu jako s objektem.
V následujícím příkladu je celočíselná proměnná i
v rámečku a přiřazena objektu o
.
int i = 123;
// The following line boxes i.
object o = i;
Objekt o
pak lze rozbalit a přiřadit k celočíselné proměnné i
:
o = 123;
i = (int)o; // unboxing
Následující příklady ukazují, jak se v jazyce C# používá balení.
// 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
Výkon
Ve vztahu k jednoduchým přiřazením jsou boxování a rozbalování výpočetně náročné procesy. Když je typ hodnoty v rámečku, musí být přidělen a vytvořen nový objekt. V menší míře je přetypování potřebné pro rozbalování také výpočetně náročné. Další informace najdete v tématu Výkon.
Zabalení
Boxování se používá k ukládání hodnot do haldy uvolňování paměti. Balení je implicitní převod typu hodnoty na typ object
nebo na jakýkoli typ rozhraní implementovaný tímto typem hodnoty. Balení typu hodnoty přidělí instanci objektu na haldě a zkopíruje hodnotu do nového objektu.
Představte si následující deklaraci proměnné typu hodnota:
int i = 123;
Následující příkaz implicitně použije operaci balení na proměnnou i
:
// Boxing copies the value of i into object o.
object o = i;
Výsledkem tohoto příkazu je vytvoření odkazu o
na objekt v zásobníku, který odkazuje na hodnotu typu int
na haldě. Tato hodnota je kopií hodnoty typu hodnota přiřazené proměnné i
. Rozdíl mezi dvěma proměnnými, i
a o
, je znázorněn na následujícím obrázku převodu:
Je také možné provést balení explicitně jako v následujícím příkladu, ale explicitní balení není nikdy vyžadováno:
int i = 123;
object o = (object)i; // explicit boxing
Příklad
Tento příklad převede celočíselnou proměnnou i
na objekt o
pomocí balení. Pak se hodnota uložená v proměnné i
změní z 123
na 456
. Příklad ukazuje, že typ původní hodnoty a objekt v rámečku používají samostatná paměťová umístění, a proto mohou ukládat různé hodnoty.
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 doesn't affect 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
*/
Unboxing
Rozbalení je explicitní převod z typu object
na typ hodnoty nebo z typu rozhraní na typ hodnoty, který implementuje rozhraní. Operace rozbalování se skládá z:
Zkontrolujte instanci objektu a ujistěte se, že se jedná o hodnotu daného typu hodnoty v rámečku.
Kopírování hodnoty z instance do proměnné value-type.
Následující příkazy ukazují operace balení i rozbalení:
int i = 123; // a value type
object o = i; // boxing
int j = (int)o; // unboxing
Následující obrázek znázorňuje výsledek předchozích příkazů:
Aby bylo rozbalení typů hodnot úspěšné za běhu, musí být položka, která je rozbalována, odkazem na objekt, který byl dříve vytvořen balením instance tohoto typu hodnoty. Při pokusu o rozbalení složky null
dojde k NullReferenceException. Pokus o rozbalení odkazu na nekompatibilní typ hodnoty způsobí InvalidCastException.
Příklad
Následující příklad ukazuje případ neplatného rozbalení a výsledného InvalidCastException
. Při použití try
a catch
se při výskytu chyby zobrazí chybová zpráva.
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);
}
}
}
Tento program vypíše:
Specified cast is not valid. Error: Incorrect unboxing.
Pokud příkaz změníte:
int j = (short)o;
na
int j = (int)o;
převod se provede a získáte výstup:
Unboxing OK.
specifikace jazyka C#
Další informace najdete v tématu Specifikace jazyka C#. Specifikace jazyka je úplným a rozhodujícím zdrojem pro syntaxi a použití jazyka C#.
Viz také
.NET feedback
The .NET documentation is open source. Provide feedback here.
Váš názor
Odeslat a zobrazit názory pro