:::: MENU ::::

Kutulama Dönüştürmesi (Boxing Conversion)

Anımsanacağı gibi tüm yapılar System.ValueType türünden türetilmiş durumdadır. System.ValueType sınıfında System.Object türünden türetilmiştir. O halde, biz herhangi bir yapı değişkenini System.ValueType yada System.Object referanslarına atayabilir miyiz? İşte bir yapının System.ValueType yada System.Object referanslarına atanmasına, kutulama dönüştürmesi ( Boxing Conversion ) denir.

Referanslar stackdeki nesnenin adresini tutamazlar. Halbuki yapı değişkenleri stackdedir. İşte ne zaman bir yapı değişkeni System.ValueType yada System.Object türlerine atanacak olsa, o yapı değişkeninin heapde bir kopyası çıkartılır ve atanan referans heapdeki bu kopyayı gösteriyor duruma gelir.

      struct Sample
	{
		//...
 	}
	
	Sample s = new Sample();
	object o;
	o = s;


Kutulama dönüştürmesinden sonra stackdeki yapı değişkeni ile heapdeki kopya tamamen farklı iki nesnedir. Birinde yapılan değişiklik diğerini etkilemez.

Stackdeki değişken programın akışı blokdan çıkarken otomatik olarak, heapdeki nesne ise çöp toplayıcı tarafından yok edilir.
Int, Long, Double gibi temel türlerde birer yapı belirttiğine göre, onlar da System.ValueType yada System.Object referanslarına atanabilir.


			int a = 100;
			object o;

			o = a; // Geçerli!

Bu durumda stackdeki int değişkenin heapde kopyası çıkartılır o artık bu kopyayı gösterir duruma gelir.

Kutulama dönüştürmesi aynı biçimde enum türleri için de uygulanmaktadır. Görüldüğü gibi her şey Object referansına atanabilir.
Kutuyu Açma Dönüştürmesi (Unboxing Conversion)

Örneğin:


		Sample s = new Sample();
		object o = s;		// Boxing Conversion

		Sample k;
		k = (Sample)o;		// Unboxing Conversion
			// Stackde yaratılan geçici nesne

Stackde oluşturulan geçici değişken kullanıldığı ifade bittiğinde yok edilir. Şüphesiz kutuyu açma dönüştürmesi yapıldığında heapdeki kopya yaşamaya devam eder.

using System;
namespace CSD
{
	class App
	{
		public static void Main()
		{
			Sample s = new Sample(10,20);
			object o = s;		

			Sample k;
			k = (Sample)o;
			Console.WriteLine("{0} {1}", k.a, k.b);

			s.a = 100;
			s.b = 200;
			Console.WriteLine("{0} {1}", k.a, k.b);

		}
	}

	struct Sample
	{
		public int a;
		public int b;

		public Sample(int a, int b)
		{
			this.a = a;
			this.b = b;
		}
	}
}

C# da küçük temel türün büyük temel türe atanması, ayrı bir kuraldır ve bir türetme ilişkisi yüzünden gerçekleşmemektedir. Int yapısı Long yapısına doğrudan atanabilir fakat bu iki yapı birbirinden bağımsız iki ayrı yapıdır. Bu durumda örneğin dinamik türü int olan bir Object referansını biz tür dönüştürme operatörüyle aşağıya doğru long türüne dönüştüremeyiz.

Örneğin:



	int a = 100;
	object o = a;

	long x = (long)o;	// Derlemeyi geçer, çalışma zmaanı
				// sırasında exception oluşur.

Fakat


	int a = 100;
	object o = a;

	long x = (int)o;	// Geçerli

Kutulama dönüştürmesi sabit atamalarında da gerçekleşir.

Örneğin:


object o = 100;

Burada 100 int türündendir. Böylece kutulama dönüştürmesi sırasında heapde int türünden bir kopyası çıkarılacaktır. “o” referansı heapdeki int türden nesneyi gösterir.

Örneğin:

	object[] objs;

	objs = new object[] { 1, 2, 3, 4, 5 };

	for (int i = 0; i < objs.Length; i++)
	{
		int x = (int)objs[i];

		Console.WriteLine(x);
	}

Örneğin:

	object[] objs;

	objs = new object[] { 1, 2.3, 3, 4, 5 };

	for (int i = 0; i < objs.Length; i++)
	{
		int x = (int)objs[i];
		// Çalışma zamanı sırasında Exception
		Console.WriteLine(x);
	}

Kaynak:Kaan Aslan Hocanın Dersinde Tuttuğum Ders Notlarıdır.


So, what do you think ?