C# Temelleri

Duygu Evrim Odabaş
7 min readFeb 9, 2021

--

Merhabalar, bu gönderide, birçok yerde karşınıza çıkabilecek olan temel C# konuları hakkında detaylı bilgiler vermeye çalışacağım. Bu konular, C# testinde bulunan sorulara göre hazırlanmıştır. Yazıyı okuduktan sonra öğrendiklerinizi testi çözerek pekiştirebilirsiniz. Bahsedeceğim konuların listesi aşağıdaki gibidir.

Değer (Value) ve Referans (Reference) Tipler
Nullable Tipler
Inheritance ( Kalıtım ) Kavramı
Interface Kavramı
Abstract Class Kavramı
Access Modifiers
Indexer Kavramı
Enumerations Type — Enum
Delegate (Temsilci) Kavramı
Predicate
Event (Olay) Kavramı
Ternary Operator
Partial Class’lar
LINQ (Language Integrated Query)

Değer (Value) ve Referans (Reference) Tipler

C# programlama dilinde value types ve reference types olmak üzere iki adet veri tipi mevcuttur.

Değer tipleri; veriyi taşıyan ve taşıdığı veriye göre bellek üzerinde yer dolduran değişken türleridir. Ayrıca belleğin “stack” bölgesinde tutulmaktadırlar. System.ValueType” sınıfından türetilirler.

int, long, float, double, decimal, char, bool, byte, short, struct ve enum değer tipleridir.

Referans türleri, bellek bölgesinde veri yerine adresi tutarlar ve o adresin gösterdiği yerde de veri tutulur.

string, object, class, interface, array, delegate ve pointer referans tipleridir.

Nullable Tipler

Bir değer türüne null değer atanamaz. Örneğin, int i = null tanımlaması bize compile-time hatası verir. C # 2.0, değer türü değişkenlerine null atamanıza izin veren Nullable yapıları tanıttı.

Nullable tipler, ilgili değer tipinin değer aralığını temsil edebilen yapılardır. Ek olarak null değerler de içerebilirler. Referans tipine değil, değer tipine null atanmasına izin vermektedirler. Özet olarak, değişkenin değer içerip içermediği konusunda bize bilgi vermektedir. Nullable tipler, System.Nullable<T> türündedirler.

Aşağıdaki örnekte bulunan tanımlamada, i değişkenine, -2147483648 ile 2147483647 arasında herhangi bir değer veya null değer atanabilir.

Nullable type örnek tanımlama

Aşağıdaki kod parçasında Nullable kullanımına ait bir örnek verilmiştir. HasValue, nesneye bir değer atanmışsa true döndürür; herhangi bir değer atanmamışsa veya null değer atanmışsa, false döndürür.

Nullable type örnek kod parçası

Aynı kodu HashValue ile kontrol sağlamadan yazmış olsaydık ve değişkene null değer atamış olsaydık, runtime exception oluşmuş olacaktı.

Geçersiz nullable type kullanımı

Inheritance (Kalıtım) Kavramı

Inheritance (Kalıtım) kavramı, nesneye yönelik programlamanın temel unsurlarından biridir. Sınıflar arası hiyerarşiyi sağlar ve yazılımda sürdürebilirlik için kullanılan en önemli tekniklerdendir. Kalıtımda, Derived Class ve Base(temel) Class adında iki adet temel terim vardır. Kalıtım veren sınıfa base class, base class’tan özellikleri kalıtımla miras alan alt sınıflara derived (türetilmiş) class adı verilmektedir. Örneğin, “Sekil” ve “Dikdortgen” isimli iki adet class’ımız olduğunu varsayalım. Bu durumda şekillere ait temel bilgileri içeren “Sekil” isimli class base class olacaktır. “Dikdortgen” isimli class ise, “Sekil” class’ı içerisinde bulunan özellikleri miras alacaktır ve kendi içerisinde özelleşeceği başka özelliklere sahip olacaktır.

Base Class
Derived Class

Yukarıdaki işlemler sonucunda program çıktısı aşağıdaki gibidir.

Program çıktısı

Interface Kavramı

Bu bölümde nesneye yönelik programlamanın temel bileşenlerinden olan interface’lerden söz edeceğim. Interface’ler, kendilerini implement eden classlara rehberlik görevi üstlenirler. Bu rehberlik kavramından da anlaşılacağı gibi, interface tanımları içerisinde kod blokları bulunmamalıdır. Interface yapılar sadece içi boş tanımlamalardan ibarettir. Bu içi boş tanımlamalar Interface’in kullanılacağı class içerisinde işlevine uygun şekilde doldurulmaktadır. Ayrıca bir class’a birden çok interface eklemek mümkündür.

Aşağıda interface kullanımını içeren bir senaryo oluşturulmuştur. Islem isimli class içerisinde alanHesapla ve cevreHesapla isimli iki adet içi boş method tanımlanmıştır. Bu methodlar daha sonra Islem sınıfını implement eden sınıflar tarafından doldurulacaktır.

Daha sonra, tanımlanan interface’i implement eden Cember isimli bir sınıf oluşturulmuştur. Bu sınıf içerisinde çemberin alan ve çevre bilgilerini hesaplayan içi boş methodlar doldurulmuştur. Aynı şekilde Kare isimli bir sınıf daha oluşturulmuş ve bu sınıf da Islem sınıfını implement etmiştir.

Son olarak Program.cs içerisinde birer instance oluşturulmuştur. İlgili kod çıktısı aşağıdaki gibidir.

Program çıktısı

Abstract Class Kavramı

Abstract class’lar, nesneye yönelik programlamanın önemli bileşenlerinden bir tanesidir. Abstract Class, ortak özellikli Class’lara Base Class olma görevini üstlenir. Burada bahsedilen Base classta bulunan method ya da özelliklerin, base class’ı kalıtım ile kullanan sınıflarda ihtiyaç duyulduğu şekilde kullanılır. Base class içinde abstract ile işaretlenen metodlar ve propertyler bu sınıftan kalıtım alan her sınıfta yazılmak ve implement(uygulanmak) zorundadırlar. Bir sınıf yalnızca bir abstact sınıfı miras alabilir. Ayrıca abstact tanımlamalar private olarak yapılamazlar.

Access Modifiers

Koda dışarıdan yapılmak istenen erişimlerin sınırlarını belirlemek için access modifiers (erişim belirleyiciler) kullanılmaktadır. Erişim belirleyicileri ve açıklamaları aşağıdaki gibidir.

  1. public : Bu erişim belirleyici tipinde hiç bir kısıtlama yoktur. Tamamen erişilebilir durumdadır.
  2. protected : Sadece tanımlandığı sınıfın içinde ve o sınıftan türeyen diğer sınıfların içinde erişilebilirdir. Farklı paketlerden erişim sağlanamaz.
  3. internal: Aynı program içerisinden erişimde herhangi bir kısıtlama yoktur ancak farklı program içerisinden erişilemez durumdadır.
  4. private : Yalnızca tanımlandığı sınıfın içerisinde erişilebilir.

Indexer Kavramı

C# programlama dilinde Array yapısında index operatörü köşeli parantez ([]) ile kullanılmaktadır. Örneğin bir dizinin x. index’indeki elemanına dizi[x] şeklinde ulaşabiliyoruz. Indexer sayesinde bir sınıfı dizi olarak kullanabiliriz. Tıpkı dizilere eriştiğimiz gibi, indexer tanımlamalarına da köşeli parantezler yardımıyla erişilmektedir.

Örneğin Lesson isimli bir class’ımız olsun ve ders isimlerini önce bir Array içerisinde, daha sonra da indexer yardımıyla Lesson class’ı içerisinde tutalım.

Indexer Kullanmadan Tanımlama

Yukarıdaki kod parçasında bir List tanımlayarak ders isimlerini sırayla List içine attık. Ancak bunu Indexer kullanarak da yapabilirdir.

Aynı işlemin Indexer kullanarak yapılmış hali yukarıdaki gibidir. İlk olarak Lesson isimli class oluşturup ilgili öznitelik tanımlamaları yapılmıştır. Daha sonra, indexer kullanarak Lesson class’ımıza indekslenebilme özelliği verilmiştir. Son olarak, Program.cs içerisinde Lesson sınıfı çağırılarak dersler sırasıyla içerisine atanmıştır. Kod çalıştırıldığı zaman ekrana 1.index’te bulunan ders olan “Mikroişlemciler” basılacaktır.

Enumerations Type — Enum

Enum, bir grup sabiti (değiştirilemez / salt okunur değişkenler) temsil eden özel bir sınıftır. Basitçe enum kullanımını gösteren kod örneği aşağıdaki gibidir. Enum’ların ilk öğesi 0, ikinci öğesi 1 değerine sahiptir ve bu şekilde devam etmektedir. Enum içerisindeki bir öğenin integer değerini almak istediğimiz zaman, öğeyi int tipine dönüştürmemiz gerekmektedir. Bu şekilde aşağıdaki görselde bulunan “Action” öğesinin integer değerinin 0 olduğunu, diğer öğelerin de sırasıyla 1 ve 2 olduğunu göreceksiniz.

Program çıktısı 0 olacaktır.

Delegate (Temsilci) Kavramı

C# programlama dilinde, bir veya daha fazla metodu gösteren referans türünden nesnelerdir. Referans tipli yapılardır. Methodlarla aynı şekilde tanımlanmaktadırlar. Bir delegate tanımlandıktan sonra, bir veya birden çok method ilgili delegate’e atanarak kullanılmaktadır.

Metodun dönüş tipinin ve parametrelerinin ne olduğuna imza (signature) adı verilir ve delegate temsil edeceği metodun imzasını beklemek zorundadır.

Birden fazla metodu tek komutla çalıştırmak, bir metodu bir değişkene değer olarak atamak ve metodlara başka bir metodu parametre olarak göndermek için Delegate kullanabiliriz.

Delegate kullanımına ait örnek kod parçası aşağıdaki gibidir.

Delegate Örnek Kullanım

Func, değer döndüren methodlar için kullanılmaktadır. Action’lar ise, herhangi bir dönüş değerine sahip olmadığımız methodları temsil etmektedir. Özetle, delegate void olan bir methodu gösterdiğinde Action kullanılmalıdır.

Predicate

Predicate, bir parametre almaktadır ve bu parametrenin belirli kriterlere uygun olup olmadığına göre true ya da false değer döndüren bir delegate’dir. Boolean dışında bir veri tipi döndüremez. Predicate, aşağıdaki gibi tanımlanır.

predicate signature

Diğer delegate türleriyle aynı şekilde, Predicate’ler anonim method ve lambda expression ile tanımlanabilir.

Predicate Delegate Kullanımı
Anonim methodlarda predicate delegate kullanımı
Lambda expression predicate delegate kullanımı

Yukarıdaki kod parçalarının çıktıları sırasıyla ekrana basıldığı zaman sonuç aşağıdaki gibi olmalıdır.

Predicate delegate örnek çıktısı

Event (Olay) Kavramı

Event’lar, tuşa basma, tıklamalar, fare hareketleri gibi kullanıcı eylemleri veya sistem tarafından oluşturulan bildirimler gibi bazı durumları kapsamaktadır. Süreçler arası iletişim kurmada çok kullanılmaktadırlar.

Bir olayın(event) tanımlanabilmesi için mutlaka bir temsilci (delegate) tipi ile eşleştirilmesi gerekmektedir.

Ternary Operator

Koşul tarafından belirtilen ifade doğruysa, statement1'in sonucu ternanry operatör tarafından döndürülür. Yanlışsa, statement2'nin sonucu döndürülür. 3 operand almaktadır. If-Else bloğu ile yaptığımız işlemleri tek satırda halletmek istediğimiz zaman gayet kullanışlıdır. Kodu daha kısa ve daha anlaşılır kılmaktadır. Ternary operator kullanımı kodun uzunluğunu azaltabilir ancak çok fazla koşulu değerlendirdiğimiz zaman kodun mantığını anlamamızı zorlaştırır. Bu nedenle basit if-else yapıları için daha kullanışlıdır. Kullanırken bunu da göz önünde bulundurmak gerekir.

Aşağıdaki kod parçalarında aynı işlem ilk olarak if-else bloklarıyla, daha sonra da ternary operator kullanılarak yapılmıştır.

Partial Class

Partial Class, bir class’ı birden fazla class olarak bölmemize olanak sağlamaktadır. Bu nedenle tek bir sınıf birden çok .cs dosyasında bulunuyor olmaktadır. Partial Class’lar, fiziksel olarak birden çok parça ile oluşsa da, çalışma zamanında bütün elemanları içinde bulunduran tek bir class olarak görev yapar. Büyük sınıf dosyalarını parçalama, öznitelik ve methodları birbirinden ayırma ve aynı class üzerinde farklı yazılımcıların çalışmasına olanak sağlama gibi avantajlar yaratmaktadır.

Aşağıdaki uygulamada, Movie sınıfı üzerinde öznitelikleri ve metotları ayırmak adına partial class’lar kullanılmıştır. Bu amaçla partial class barındıran Movie.cs ve Movie_Method.cs isimli iki adet dosya oluşturulmuştur. Movie.cs dosyasında name ve imdb bilgileri tutulmuştur.

Movie_Method.cs isimli dosyada Movie class’ı için oluşturmak istediğimiz AddMovie methodu oluşturulmuştur. Bu iki dosyada dikkat edilmesi gereken önemli noktalardan biri, iki dosyadaki class’ın da “Movie” olarak adlandırılmış olmasıdır. Partial class ile fiziksel olarak parçalanmış olan class’ların birleştirilebilmesi için, birleştirilmek istenen class’lar aynı isimlere sahip olmalıdır.

Son olarak, Program.cs içerisinde ilgili partial class’ların kullanımına ait örnek verilmiştir.

LINQ (Language Integrated Query)

LINQ, C # 3.0 ile hayatımıza giren farklı veri kaynaklarından sorgulama yapabilmemize olanak sağlar. Bir sorguyu tek bir SQL sorgusuna çevirmektedir. Aşağıdaki kod parçasında LINQ kullanımına ait örnek verilmiştir. Örnekte names dizisindeki örneklerden ‘i’ içeren örnekler döndürülüp ekrana basılmıştır. Çıktı olarak ekrana sadece “Evrim” basılmaktadır. Bu işlemi döngü içerisinde de hesaplayabilirdik ancak LINQ kullanarak sonucu bulmak çok daha kolaydır.

LINQ Örnek Kullanım
LINQ örnek sorgu

Zaman ayırdığınız için teşekkürler. Umarım faydalı olmuştur🙂

--

--