İlkay İlknur

just a developer...

C# 6.0 - Primary Constructors

Bir önceki yazımızda C# 6.0 ile beraber getirilmesi düşünülen özelliklere genel bir bakış atmıştık. Şimdi sıra geldi her bir özelliği teker teker incelemeye. İlk sırada Primary Constructorlar var.

Nedir ? Ne işe Yarar ?

Primary constructorlar, bizim constructor parametrelerini doğrudan class veya struct tanımı esnasında tanımlamamızı sağlarlar. Böylece compiler da arka planda bizim verdiğimiz parametreleri kabul eden bir constructor yaratır. Hemen bir örnek vermemiz gerekirse

C# 6.0 ile Primary Constructor Tanımı

public class Event(int id, string name, string location)
{

}
C# 6.0 Öncesinde Nasıl Yazıyorduk  ? 
public class Event
{
    public Event(int id, string name, string location)
    {

    }
}

En basit anlamıyla baktığımızda primary constructorların temel işlevi yukarıda gördüğünüz gibi bizim daha az kod yazmamızı sağlamak. Şimdi işleri biraz daha karmaşıklaştıralım.

Ya Birden Fazla Constructor Olursa ?

Yazdığımız sınıflarda her zaman tek bir constructorımız olmuyor haliyle. Peki birden fazla contructor olduğunda işler nasıl işliyor ?

Özelliğin adı Primary Contructors :) İşte Primary sözcüğü tamda bu noktada devreye giriyor. :) Primary constructor syntaxı ile tanımladığınız constructor o classın öncelikli constructorı oluyor. Yani 2. bir constructorınız varsa o constructor mutlaka primary constructorı çağırmalı.

Yukarıdaki uyarı da bir önceki paragrafta söylediklerimizi onaylıyor. O zaman uyarıdan kurtulalım :)

public class Event(int id, string name, string location)
{
    public Event(int id, string name) : this(id, name, string.Empty)
    {

    }
}

Inheritance İşin İçine Girerse ?

Peki diyelim ki primary constructor tanımladığımız sınıf başka bir sınıftan türüyor. Bizim primary constructor tanımladığımız sınıfta primary constructor çalışırken türediği sınıfın constructorına istediğimiz parametreleri nasıl geçeriz ?

public class Event(int id, string name, string location)
{

}

public class SportEvent(int id, string name, string location, string teams)
    : Event(id, name, location)
{

}

Peki Partial Classlar ?

Partial classları code generation senaryoları haricinde kullanmadığınızı düşünüyorum :) Ancak aklınıza şu şekilde bir soru gelebilir : Peki ya ben farklı partial class tanımlarında farklı primary constructorlar tanımlarsam ne olur ? Daha doğrusu tanımlayabilir miyim ?

Cevap : Hayır. Partial class tanımlamalarının sadece 1 tanesinde primary constructor tanımlaması yapabilirsiniz. Eğer birden fazla class tanımında primary constructor tanımlarsanız derleme hatası alırsınız.

Bu Kod Derlenmez !!!

Bu Kod Derlenir
public partial class Event(int id, string name,string location)
{
    public Event(int id, string name) : this(id, name, string.Empty)
    {

    }
}

public partial class Event
{

}

Nerede Bu Parametreler ? Ulaşamıyorum...

En can alıcı noktayı sona bıraktım :) Eğer primary constructors özelliğini kurcalamaya başlarsanız primary constructorla gelen parametrelere bazı yerlerde ulaşabildiğinizi bazı yerlerde de ulaşamadığınızı göreceksiniz. Örneğin aşağıdaki kodlarda ilgili parametre değerlerine ulaşabiliyoruz.

public class Event(int id, string name, public string location)
{
    public int Id = id;
    public string Name { getset; } = name;
}

Not : Yukarıdaki koddaki 2. satır C# 6.0 ile beraber gelen auto propertyler initializer. Özellikle ilgili kısa bilgi almak için buraya bakabilirsiniz.

Yukarıda yapabildiklerimize karşın aşağıdaki durumlarda da constructora geçilen değerlere ulaşamıyoruz.

Bu durumdan kurtulmanın bir yolu var aslında. Class tanımı içerisinde kendi değişkenlerimizi tanımlayarak constructora geçilen parametrelerin değerleri tanımladığımız değişkenlere atayabiliriz.

Örneğin,

public class Event(int _id, string _name, string _location)
{
    int id = _id;
    string name = _name;
    string location = _location;

    public void Foo()
    {
        string str = id.ToString();
    }
}

Yukarıdaki çözüme baktığımızda aslında istediğimiz sonucu elde edebildik. Ancak tabi bazı sorunlar var. Öncelikli olarak bu primary constructors özelliği bizim daha az kod yazmamızı sağlamıyor muydu ? Biz primary constructor kullanacağız diye bu sefer son derece çirkin bir kod yazdık :) Primary constructor parametreleriyle class'ım içerisindeki değişkenlere aynı ismi veremeyeceğim için constructor parametrelerimin önüne _ koymak zorunda kaldım vs... Özetle ortalık karman çorman artık...

Tüm bu durumları neyseki C# takımı önceden düşünmüş ve bizi yukarıdaki kötü kodu yazmaktan kurtarmışlar.

Eğer primary constructor tanımlarken constructor parametrelerin başına access modifierları yazarsanız compiler arka planda sizin verdiğiniz access modifierına sahip bir değişken yaratıyor ve constructora geçilen değeri doğrudan bu değişkene atıyor.

public class Event(private int id, public string name, public string location)
{
    public override string ToString()
    {
        string str = "Name=" + name + " Location=" + location;
        return str;
    }
}

Bitirirken

Primary Constructorlar gördüğünüz gibi bizim kod yazmamızı oldukça kolaylaştırıyor. Ancak genel yapıya baktığımızda bu özellikle ilgili mutlaka bilmemiz gereken detaylar da var. Bu detayları bilmediğimizde ortada takılıp kalmamızda oldukça muhtemel. C# 5.0 async ile beraber aslında programlama dilinde tahmin edilebilir yapılar yerine bilinmesi gereken yapılar tarafına doğru bir kayma var. Neyse bu konu oldukça uzar gider. Bende bu yazıyı bitiremem. Başlı başına bir yazı konusu bu. Umarım faydalı olmuştur. Not : Blog yazıları haricinde sosyal medya üzerinden anlık paylaşımlarımı Twitter ve  Facebook'tan takip edebilirsiniz.


Yorum Gönder