C# IClonable ile Referans Tiplerini Klonlamak

Bilindiği üzere referans tipleri belleğin heap bölgesinde tutulmaktadır. Bu durumun sonucu olarak iki referans tipi arasında bir atama işlemi söz konusu olduğunda, aslında bu referans tiplerinin heap bellek bölgesinde yer alan adresleri eşitlenmektedir. Böyle olunca da referans tiplerinin her hangi birisinde yapılan değişiklik diğerini de otomatikman etkileyecektir. Bu referans tiplerinin değer tiplerinden farklı olduğu bi yönüdür. Çünkü değer tiplerinde bir eşitleme söz konusu olduğunda nesnenin yenisi yaratılmaktadır.

Referans tiplerinde de biz değer tiplerinde olduğu gibi eşitleme yaptığımızda bu referansların birbirlerini etkilememelerini isteyebiliriz. Bu durumda IClonable arayüzünü uygulayarak referans tipinin klonlanmasını sağlayabiliriz. Bunun nasıl yapıldığına geçmeden önce iki referans tipinin birbirine eşitlenmesi sonucu nasıl adreslerinin eşitlendiğine bir örnek verelim.


public class Araba
    {
        public string Marka { get; set; }
        public int Model { get; set; }

        public Araba()
        {
            this.Marka = "Opel";
            this.Model = 2010;
        }
        public Araba(string marka, int model)
        {
            this.Marka = marka;
            this.Model = model;
        }
        public override string ToString()
        {
            string arabaBilgisi = "Marka: " + Marka.ToString() 
                    + " Model: " + Model.ToString();
            return arabaBilgisi;
        }
    }

   
  static void Main(string[] args)
        {
            Araba araba1 = new Araba();
            // araba1 nesnesinin özelliklerini yazdırıyoruz.
            Console.WriteLine(araba1.ToString()); 

            Araba araba2;
            araba2 = araba1;
            // araba2 nesnesinin özelliklerini yazdırıyoruz.
            Console.WriteLine(araba2.ToString()); 

            araba2.Marka = "Fiat";
            araba2.Model = 2009;

            Console.WriteLine(araba2.ToString());
            Console.WriteLine(araba1.ToString());
            Console.ReadLine();
        }

Program Çıktısı :


Bu örneğimizde olduğu gibi araba1 nesnesi önce yaratılmış daha sonra araba2 = araba1 denerek araba2 nesnesine atanmıştır. Bu durumda araba2 nesnesine yapılan değişiklik doğrudan araba1 nesnesini etkilemiştir. Bu durumun nedeni atama yapılırken yukarıda anlattığımız şekilde referans tiplerinin heap bellek bölgesinde yer alan adresleri eşitlenmesidir.

Gelin şimdi de IClonable arayüzünü kullanarak bu durumu nasıl çözeceğimize bakalım:


public class Araba:ICloneable
    {
        public string Marka { get; set; }
        public int Model { get; set; }

        public Araba()
        {
            this.Marka = "Opel";
            this.Model = 2010;
        }
        public Araba(string marka, int model)
        {
            this.Marka = marka;
            this.Model = model;
        }

        public override string ToString()
        {
            string arabaBilgisi = "Marka: " 
               + Marka.ToString() + " Model: " + Model.ToString();
            return arabaBilgisi;
        }

        #region ICloneable

        public object Clone()
        {
            return new Araba(this.Marka,this.Model);
        }

        //NOT: Bu şekilde de Klonlama yapılabilmektedir. 
        //Fakat bu yöntemde eğer clasın içinde başka bir 
        //reference type varsa o kopyalanmaz.
        //public object Clone()
        //{
        //    return this.MemberwiseClone();
        //}
        #endregion
    }

static void Main(string[] args)
        {
            Araba araba1 = new Araba();
            // araba1 nesnesinin özelliklerini yazdırıyoruz.
            Console.WriteLine(araba1.ToString()); 

            Araba araba2;
            araba2 = araba1;
            // araba2 nesnesinin özelliklerini yazdırıyoruz.
            Console.WriteLine(araba2.ToString()); 

            araba2.Marka = "Fiat";
            araba2.Model = 2009;

            Console.WriteLine("araba2: " + araba2.ToString());
            Console.WriteLine("araba1: " + araba1.ToString());
            Console.ReadLine();
        }

Programın Çıktısı :


İkinci örneğimizde IClonable arayüzü implement edilerek bu arayüzün Clone metodu kullanılmıştır. Ve bu sayede atama yapılırken Clone metodu kullanılarak yeni bir araba nesnesi ve adresi oluşturulması sağlanmıştır. Programın çıktısından açıkça görüldüğü gibi bu sefer araba2 nesnesine yapılan değişiklikler araba1 nesnesini etkilememiştir.

Burada kod içerisinde commentli olarak yazılmış önemli bir nokta var.


        //NOT: Bu şekilde de Klonlama yapılabilmektedir. 
        //Fakat bu yöntemde eğer clasın içinde başka bir 
        //reference type varsa o kopyalanmaz.
        //public object Clone()
        //{
        //    return this.MemberwiseClone();
        //}

Klonlama bu şekilde de yapılabilir fakat Araba nesnesi içerisinde bir referans tipi tanımlı ise bu metod bu referans tipini klonlamaz yani ataması yapılan nesnenin içerisindeki referans tipinin adresi aynen kopyalanır. Bu yüzden bu metodu eğer sınıfınızda referans tipi tanımlamadıysanız kullanmanız gerekmektedir.

0 yorum :

Yorum Gönder