Menu
Coddy logo textTech

Generics (Sınıflar ve Metotlar)

Coddy'nin C# Journey'sinin Nesne Yönelimli Programlama bölümünün bir parçası — ders 42 / 70.

Generics, tip güvenliğini korurken herhangi bir veri tipiyle çalışan sınıflar ve metotlar yazmanıza olanak tanır. IntList, StringList ve DoubleList için ayrı sınıflar yazmak yerine, hepsini işleyen tek bir generic sınıf yazarsınız.

Generic bir sınıf, genellikle açılı ayraçlar içine alınmış ve T olarak adlandırılan bir tür parametresi kullanır:

public class Box<T>
{
    private T content;
    
    public void Store(T item) => content = item;
    public T Retrieve() => content;
}

// Farklı türlerle kullanım
Box<int> intBox = new Box<int>();
intBox.Store(42);

Box<string> stringBox = new Box<string>();
stringBox.Store("Hello");

Box<int> oluşturduğunuzda, derleyici her T'yi int ile değiştirir. Bu, derleme zamanı tür denetimi sağlar - bir int kutusunda yanlışlıkla bir dize saklayamazsınız.

Generic metotlar benzer şekilde çalışarak tek bir metodun farklı türler üzerinde işlem yapmasına olanak tanır:

public static void Swap<T>(ref T a, ref T b)
{
    T temp = a;
    a = b;
    b = temp;
}

int x = 1, y = 2;
Swap(ref x, ref y);  // x=2, y=1

Derleyici türü argümanlardan çıkarır, bu nedenle Swap<int> ifadesini açıkça yazmanıza gerek kalmaz. Generic'ler, List<T> ve Dictionary<TKey, TValue> gibi koleksiyonların temelidir ve yeniden kullanılabilir, tür güvenli kod yazılmasını sağlar.

challenge icon

Görev

Kolay

Herhangi bir türdeki öğeleri tutabilen ve yönetebilen genel bir Storage<T> sistemi oluşturalım. Generics'in gücünü gösteren, yeniden kullanılabilir bir kapsayıcı sınıfı oluşturacaksınız - bir kez yazın, tam sayılarla, dizelerle veya başka herhangi bir türle kullanın!

Kodunuzu iki dosya halinde düzenleyeceksiniz:

  • Storage.cs: DataStorage ad alanında (namespace) genel bir Storage<T> sınıfı oluşturun. Depolama kapsayıcınız şunları yapmalıdır:
    • Öğeleri tutmak için T türünde özel bir diziye ve kaç öğenin saklandığını takip eden bir Count özelliğine sahip olmalıdır
    • Dahili diziyi başlatmak için yapıcı metodunda (constructor) bir kapasite kabul etmelidir
    • Yer varsa bir öğe ekleyen bir Add(T item) metoduna sahip olmalıdır
    • Belirtilen dizindeki öğeyi döndüren bir Get(int index) metoduna sahip olmalıdır
    • Tüm saklanan öğeleri ", " ile birleştirilmiş olarak döndüren bir GetAll() metoduna sahip olmalıdır
  • Program.cs: Ana dosyanızda, genel sınıfınızın iki farklı türle çalışmasını gösterin. Bir Storage<int> ve bir Storage<string> oluşturun, her birine öğeler ekleyin ve aynı sınıfın her iki türle de sorunsuz çalıştığını gösterin.

Dört girdi alacaksınız:

  • Saklanacak ilk tam sayı
  • Saklanacak ikinci tam sayı
  • Saklanacak ilk dize (string)
  • Saklanacak ikinci dize (string)

5 kapasiteli bir tam sayı deposu ve 5 kapasiteli bir dize deposu oluşturun. İki tam sayıyı tam sayı deposuna ve iki dizeyi dize deposuna ekleyin.

Çıktıyı şu formatta yazdırın:

Int storage: {GetAll()}
Int count: {Count}
First int: {Get(0)}
String storage: {GetAll()}
String count: {Count}
First string: {Get(0)}

Örneğin, girdiler 42, 100, Hello ve World ise çıktı şöyle olmalıdır:

Int storage: 42, 100
Int count: 2
First int: 42
String storage: Hello, World
String count: 2
First string: Hello

Storage<T> sınıfını bir kez nasıl yazdığınıza, ancak hem int hem de string ile mükemmel şekilde çalıştığına dikkat edin - işte generics'in sihri budur! Derleyici tür güvenliğini sağlar, böylece tam sayı deponuza yanlışlıkla bir dize ekleyemezsiniz.

Kopya kağıdı

Generic yapılar, tip güvenliğini korurken herhangi bir veri tipiyle çalışan sınıflar ve metotlar yazmanıza olanak tanır.

Generic bir sınıf, genellikle açılı ayraçlar içine alınmış bir tip parametresi (genellikle T) kullanır:

public class Box<T>
{
    private T content;
    
    public void Store(T item) => content = item;
    public T Retrieve() => content;
}

Bir örnek oluştururken, T yerine geçecek tipi belirtin:

Box<int> intBox = new Box<int>();
intBox.Store(42);

Box<string> stringBox = new Box<string>();
stringBox.Store("Hello");

Generic metotlar, tek bir metodun farklı tipler üzerinde işlem yapmasına izin verir:

public static void Swap<T>(ref T a, ref T b)
{
    T temp = a;
    a = b;
    b = temp;
}

int x = 1, y = 2;
Swap(ref x, ref y);  // Compiler infers type from arguments

Generic yapılar, derleme zamanı tip kontrolü sağlar ve List<T> ile Dictionary<TKey, TValue> gibi koleksiyonların temelini oluşturur.

Kendin dene

using System;
using DataStorage;

class Program
{
    public static void Main(string[] args)
    {
        // Girdileri oku
        int num1 = Convert.ToInt32(Console.ReadLine());
        int num2 = Convert.ToInt32(Console.ReadLine());
        string str1 = Console.ReadLine();
        string str2 = Console.ReadLine();

        // TODO: 5 kapasiteli bir Storage<int> oluştur
        
        // TODO: İki tam sayıyı integer deposuna ekle
        
        // TODO: 5 kapasiteli bir Storage<string> oluştur
        
        // TODO: İki dizeyi string deposuna ekle
        
        // TODO: Çıktıyı istenen formatta yazdır
        // Int storage: {GetAll()}
        // Int count: {Count}
        // First int: {Get(0)}
        // String storage: {GetAll()}
        // String count: {Count}
        // First string: {Get(0)}
    }
}
quiz iconKendini test et

Bu ders kısa bir quiz içerir. Soruları yanıtlamak ve ilerlemeni kaydetmek için derse başla.

Nesne Yönelimli Programlama bölümündeki tüm dersler