Burak Selim Şenyurt | Struct, Class ve Default Constructors - İnanmak İstiyorum
← Kod Bazlı Workflow Service Geliştirmek ve Yayınlamak
NedirTv?com Söyleşileri – Yazılım Dünyasının Merak Edilen Soruları →
Sanıyorum 90 yıllarda en çok izlediğim dizilerden birisi The X Files (Gizli Dosyalar) idi. Her bölümde olağan dışı konuların ele alındığı ve birbirlerine tamamen zıt iki karekter olan ama bu sayede gizli dosyaların işlenmesinde birbirlerini sürekli olarak dengeleyen Ajan Dana Scully ve Fox Mulder' ın maceraları gerçeklikten uzak olsa da, benim gibi bilim kurgu severleri ekrana bağlamak için yeterliydi.
Diziyi her izleyişimde en çok hoşuma giden sahneler ise genellikle Fox Mulder' ın bir soru sorup ortağı dahil herkesi bir kaç saniyeliğine de olsa düşünmeye itmesiydi(yeni nesil argoda ifade etmek istersek dumura uğratmasıydı). Geçtiğimiz günlerde yine X Files dizisinin bir kaç bölümünü heyecanlı bir şekilde tekrardan izlerken bazen yaptığımız işte de, Ajan Fox Mulder' ın ürettiği gibi şüphe uyandırıcı soruların oluştuğunu düşünmeye başladım. Tabi soruyu hemen sormak istemiyorum. Olaya biraz daha heyecan katmakta yarar var. Bakalım bu yazımızın Fox Mulder' ı olabilecek miyim?
Konumuz C# programlama dilinin temelleri arasında sayılmaktadır. Class ve Struct tiplerinde Default Constructor(Varsayılan Yapıcı Metod) kullanımı. Bildiğiniz üzere .Net Framework Base Class Library üzerinde tiplere en üst seviyeden baktığımızda değer(Value) ve referans(Reference) türleri olarak ikiye ayırmaktayız. Struct tipleri değer türü, Class' lar ise referans türleri olarak ele alınmaktadır. Bu iki veri türününün bellekte tutuluş şekilleri, aralarındaki atamalarda gösterdikleri davranışsal farklılıklar bir kenara, özellikle kendi geliştirdiğimiz taslaklarında dikkat etmemiz gereken noktaların başında da, yapıcı metod kullanımları gelmektedir. Dilerseniz aşağıdaki kod parçasını göz önüne alarak işe koyulalım.
Bu kod parçasında Person isimli bir Class ve Product isimli bir Struct tanımlanmıştır. Her iki tip içerisinde de varsayılan yapıcı metod(Default Constructor) kullanımı söz konusudur. Ancak kodu derlediğimizde bir hata mesajı ile karşılaştığımızı görürüz.
Kural 1 geliyor : Bu Struct olmanın kurallarından birisidir. Buna göre bir Struct' ın, Class' ların aksine parametresi olmayan yapıcı metod içermesi söz konusu değildir. Çok doğal olarak aşağıdaki gibi bir kullanım tercih edilebilir.
public Person(int pId,string name,double salary)
public Product(int pId,string title,double listPrice)
Bu kez hem Class hem de Struct için parametre alan yapıcı metodlar söz konusudur. Ancak yine bir Compile Time hatası alınılması kaçınılmazdır.
Dikkat edileceği üzere Class tipi için parametreli kullanım söz konusu iken, Struct için aynı durum gerçeklenememektedir.
Kural 2 geliyor : Bir Struct için parametreli yapıcı metod kullanılması halinde, içerideki tüm alanlara ilk değerlerinin atanması gerekmektedir. Dolayısıyla Struct' ımıza ait parametreli yapıcı metod içeriği aşağıdaki gibi düzenlenirse sorun kalmayacaktır.
ListPrice = listPrice;
Şimdi kod parçasını aşağıdaki gibi değiştirdiğimizi düşünelim.
burak.PersonId = 1001;
burak.Name = "Burak Selim Şenyurt";
burak.Salary = 1;
Product mouse = new Product();
mouse.ProductId = 2001;
mouse.Title = "Microsoft Optical Mouse";
mouse.ListPrice = 9.99;
Bu sefer ne Class ne de Struct için bir yapıcı metod bildiriminde bulunulmamıştır. Kod başarılı bir şekilde derlenmiştir. Main metodu içerisinde ise her iki tipe ait nesne örnekleri oluşturulmuş ve alanlarına bazı değerler atanmıştır. Hımmm...İşte Fox Mulder sorusu geliyor?
Struct' lar için açık bir şekilde varsayılan yapıcı metod tanımlayamıyorsak eğer, nasıl oluyorda new Struct() şeklinde bir metod çağrısı yapabiliyoruz?
Çok doğal olarak burada Dana Scully olsaydı söz konusu soruyu cevaplamak için hasta üzerinde otopsi yapmaya, bir başka deyişle IL(Intermediate Language) koduna bakmaya karar verirdi Biz de böyle yapıyor olacağız. (Bu amaçla ILDASM veya Red Gate' s .Net Reflector gibi araçlardan yararlanabiliriz)
Person sınıfı için üretilen IL çıktısı aşağıdaki gibidir.
.class private auto ansi beforefieldinit Person
.field public int32 PersonId
.field public float64 Salary
Dikkat edileceği üzere varsayılan bir yapıcı metod otomatik olarak üretilmiştir. Ajan Dana Scully bu durum karşısında Product isimli Struct için de aynı durumun söz konusu olacağını düşünmektedir. Yüzünde bir tebessümle Mulder' a döner ve "Tamam Buldum" der gibi bakar. Oysaki mercekten tekrar baktığında aşağıdaki IL çıktısı ile karşılaşacaktır.
.class private sequential ansi sealed beforefieldinit Product
.field public float64 ListPrice
.field public int32 ProductId
Fark edileceği üzere burada ctor gibi bir metod tanımı bulunmamaktadır. Demek ki yanlış bir yerde arama yapılmaktadır. Scully derhal merceği ayarlar ve bu kez Main metodu içeriğine odaklanır.
 class ClassStructAndConstructors.Person burak,
 valuetype ClassStructAndConstructors.Product mouse)
L_0001: newobj instance void ClassStructAndConstructors.Person::.ctor()
L_0008: ldc.i4 0x3e9
L_000d: stfld int32 ClassStructAndConstructors.Person::PersonId
L_0013: ldstr "Burak Selim \u015eenyurt"
L_0018: stfld string ClassStructAndConstructors.Person::Name
L_001e: ldc.r8 1
L_0027: stfld float64 ClassStructAndConstructors.Person::Salary
L_002c: ldloca.s mouse
L_002e: initobj ClassStructAndConstructors.Product
L_0034: ldloca.s mouse
L_0036: ldc.i4 0x7d1
L_003b: stfld int32 ClassStructAndConstructors.Product::ProductId
L_0040: ldloca.s mouse
L_0042: ldstr "Microsoft Optical Mouse"
L_0047: stfld string ClassStructAndConstructors.Product::Title
L_004c: ldloca.s mouse
L_004e: ldc.r8 9.99
L_0057: stfld float64 ClassStructAndConstructors.Product::ListPrice
new Person() çağrısı için IL tarafında newobj çağrısını gerçekleştirilirken, new Product() satırına karşılık olarak initobj isimli bir çağrının gerçekleştirildiği görülmektedir. initobj için MSDN kaynaklarında yapılan açıklama şu şekildedir.
Bir başka deyişle initobj çağrısının uygulandığı Struct içerisindeki Primitive tipler için, varsayılan ilk değer atamaları gerçekleştirilmektedir. Buna göre sayısal değerler için 0 veya 0.0, bool için false ve referans türleri için de null değerlerin atanması söz konusudur. Açıkça ifade etmek gerekirse Struct' lar için varsayılan bir yapıcı metod söz konusu olmasa dahi, IL tarafında bu fonksiyonelliği üstelenen bir çağrı yapılmaktadır (Base Class Library Team tarafından bu durum implicit default constructor) olarak adlandırılmaktadır.
Ajan Scully gözlerini mercekten kaldırır ve Fox' a döner. Bu kez yüzünde haklı bir tebessüm vardır ve "Endişelerin boşunaymış Mulder. Uzaylıların bu işle hiç bir alakası yok" der Başka bir macerada görüşünceye dek hepinize mutlu günler dilerim.
ClassStructAndConstructors.rar (21,32 kb) [Örnek Visual Studio 2010 Ultimate RTM sürümü üzerinde geliştirilmiş ve test edilmiştir]
Etiketler : c#, c# temelleri, destructor, constructor
Konumuz C# programlama dilinin temelleri arasında sayılmaktadır. Class ve Struct tiplerinde Default ...
Çok güzel bir yazı olmuş elinize sağlık, default constructor olayını hiç düşünmemiştim. Kullanıyoruz ama, biride içini açıp bakmalı. Harbiden içini açıp bakmışsınız .
Bir araları kafama feci takıldığından soruyorum, belki buda bir X-Files bölümü olabilirmi bilmem ama .
public struct Kategori
public List<Kategori> Kategoriler = new List<Kategori>();
Struct içinde şöyle bir yazım biçimi hemen "'StructAndClass.Program.Kategori.Kategoriler': cannot have instance field initializers in structs" şeklinde hata veriyor :O. Ama bu bir class olsaydı.
ozaman "build succeeded!" (Y). Ama struct'ta da biçare ne yaptım bende aşağıdaki gibi bir constructor içinde elimle tanımladım.
public List<Kategori> Kategoriler;
public Kategori (string parametreninbiri)
aslında sanırım bütün bu anlattıklarınız buna da bir cevap oluyor gibi. Çünkü bu struct'ların bir "ctor" yerine "initobj" olayı varsa bu "initobj" class'larda olduğu gibi içindeki collectionlarıda construct etmiyor demek ki.
28 Eylül 2010 - Yanıtla
Hocam bundan sonra Star Wars'ada geçermiyiz.
Amlatım mükemmel olmuş elinize emeğinize dilinize sağlık.
Hocam sizi yakında sci-fi senaristi olarak görürmüyüz.
Şahane olmuş makale. Aklınıza ve parmaklarınıza sağlık
Valla aslında bunu düşünmedim değil. Hani ille de teknik bir içerik yazmak şart olmamalı. Belki bir gün bir deneme yazısı yayınlayabilirim. Zaten Gravatar' ınızdaki profesor Emett ile büyümüş birisiyim Yani bir eğilim var bilim kurguya karşı
Yazınız çok açıklayıcı ve ilgi çekici, elinize sağlık ..
30 Eylül 2010 - Yanıtla
Bir X-Files hayranı olarak heyecanla okudum. Çok keyif aldım. Elinize sağlık.
Daha az teknik, daha bir kurgu olan yazılarınızı dört gözle bekliyorum.