Altbilgi içeriğine atla
Iron Academy Logo
C# Öğrenin
C# Öğrenin

Diğer Kategoriler

C# Genellikleri (Generics) Uzmanlaşma

Tim Corey
38dk 51s

C#'taki generics, dile eklenmesinden bu yana ayrılmaz bir parçası haline gelmiştir ve her ne kadar çalışma mantığı tüm geliştiriciler tarafından tam olarak anlaşılmasa da birçok fayda sağlamaktadır. C#'da Generics Yaratma ve Yeni Özellikler adlı videosunda, Tim Corey generics'in neden önemli olduğunu, nasıl oluşturulacağını ve pratik uygulamalarını açıklar.

Bu makale, C# generics için kapsamlı bir rehber sunmakta ve konuyla ilgili Tim Corey'nin videosundan değerli bilgiler sunmaktadır. Generics'in temellerini, tür güvenliğini, performans faydalarını ve pratik uygulamaları kapsar. Makale ayrıca generic metodlar, sınıflar, arayüzler yaratmayı ve generics'e kısıtlamalar uygulamayı keşfeder. Ek olarak, gerçek dünya kullanım alanları ve generics'i kullanarak verimli, tür güvenli kod yazmanın önemi vurgulanır.

Giriş

C# generics, geliştiricilerin herhangi bir veri tipiyle çalışan sınıfları, metodları, arayüzleri ve koleksiyonları tanımlayarak esnek, yeniden kullanılabilir ve tür güvenli kod yaratmaları için güçlü bir yol sunar. Generic bir sınıf veya metod kullanarak, geliştiriciler herhangi bir veri tipini temsil edebilecek bir generic tür parametresi (örneğin, T) tanımlayabilirler. Bu, kodun çoğaltılması gereksinimini ortadan kaldırır ve tür güvenliğini derleme sırasında sağlarken, kodun yeniden kullanılabilirliğini artırır. List ve Dictionary<TKey, TValue> gibi jenerik koleksiyon sınıfları, farklı veri türlerinin verimli bir şekilde işlenmesine olanak tanırken, jenerik arabirimler ve jenerik delege, birden çok tür parametresi ile çalışabilen özel jenerik türlerin oluşturulmasını sağlar. Generics kullanarak, geliştiriciler kod verimliliğini en üst düzeye çıkarabilir ve generic olmayan sınıfların dezavantajlarını en aza indirebilirler. Bu esneklik, performanstan veya tür güvenliğinden ödün vermeden daha fazla yeniden kullanılabilir kod oluşturulmasına olanak tanır.

Tim, (0:00)'da konuyu tanıtarak C#'da generics'in yaygın kullanımını vurgular. Generics'in neden gerektiğini açıklamayı ve onları nasıl etkili şekilde oluşturacağını ve kullanacağını göstermeyi amaçlamaktadır.

Proje Oluşturma

Tim, generics'i gösterme amacıyla tamamen konsol uygulamasına odaklanabilmek için "GenericsDemoApp" adlı yeni bir konsol uygulaması oluşturarak başlar. .NET 8 ve Visual Studio 2022'yi kullanarak projeyi kurar.

Generics'in Temelleri

Tim, genel tür kavramını açıklamak için List sınıfını kullanan bir örnekle (2:22) başlar. Generics, bir koleksiyonun tutabileceği elemanların türünü belirtmeye, tür güvenliği sağlamaya ve çalışma zamanı hatalarından kaçınılmasına olanak tanır.

List<int> numbers = new List<int> { 1, 2, 3 };
List<string> strings = new List<string> { "Tim", "Corey", "Sue" };
List<int> numbers = new List<int> { 1, 2, 3 };
List<string> strings = new List<string> { "Tim", "Corey", "Sue" };

List, yalnızca tamsayıların sayılar listesine ve yalnızca dizelerin dizeler listesine eklenebilmesini sağlar.

Tür Güvenliği ve Verimlilik

Tim, generics'in sağladığı tür güvenliğinin önemini vurgular. Derleyici tasarım zamanında türleri kontrol ederek, tür uyumsuzluklarını önler ve güvenli bir kod yürütülmesini sağlar. Generics ayrıca boxing ve unboxing'i engelleyerek daha verimli kod sağlar.

Genel Olmayan Koleksiyonların Verimsizliği

Genel olmayan koleksiyonları kullanmanın verimsizliğini göstermek için, Tim bir Liste yaratır ve nasıl farklı türlerde nesneler tutabileceğini gösterir.

List<object> objects = new List<object> { "Tim", 4, 3.6m };
List<object> objects = new List<object> { "Tim", 4, 3.6m };

Genel olmayan koleksiyonların kullanımının, tür uyumsuzluklarına ve boxing ve unboxing nedeniyle verimsizliklere yol açabileceğini açıklar.

Performans Karşılaştırması

Tim, (6:15)'te Listve Listkullanarak bir milyon öğe eklemenin performans karşılaştırmasını yapar. Her işlem için geçen süreyi ölçmek için bir Kronometre kullanır.

Stopwatch stopwatch = new Stopwatch();
stopwatch.Start();

for (int i = 1; i <= 1_000_000; i++)
{
    objects.Add(i);
}

stopwatch.Stop();
Console.WriteLine($"List of object elapsed time: {stopwatch.ElapsedMilliseconds} ms");

stopwatch.Restart();

for (int i = 1; i <= 1_000_000; i++)
{
    numbers.Add(i);
}

stopwatch.Stop();
Console.WriteLine($"List of int elapsed time: {stopwatch.ElapsedMilliseconds} ms");
Stopwatch stopwatch = new Stopwatch();
stopwatch.Start();

for (int i = 1; i <= 1_000_000; i++)
{
    objects.Add(i);
}

stopwatch.Stop();
Console.WriteLine($"List of object elapsed time: {stopwatch.ElapsedMilliseconds} ms");

stopwatch.Restart();

for (int i = 1; i <= 1_000_000; i++)
{
    numbers.Add(i);
}

stopwatch.Stop();
Console.WriteLine($"List of int elapsed time: {stopwatch.ElapsedMilliseconds} ms");

Sonuçlar, Listüzerine tamsayı eklemenin, boxing ve unboxing'in olmaması nedeniyle List'e eklemekten önemli ölçüde daha hızlı olduğunu gösterir.

Performans Karşılaştırması

Bir Tür Kontrolcüsü Metodu Oluşturma

Tim, (10:14)'te TürKontrolcüsü adında genel bir metod oluşturmayı gösterir. Bu metod, verilen bir değerin türünü kontrol edip yazdırır ve türlerin esneklik ve gücünü gösterir.

public static void TypeChecker<t>(T value)
{
    Console.WriteLine($"Type: {typeof(T)}, Value: {value}");
}
public static void TypeChecker<t>(T value)
{
    Console.WriteLine($"Type: {typeof(T)}, Value: {value}");
}

TürKontrolcüsü metodu, generic parametre T'nin türünü belirlemek için typeof operatörünü kullanır ve hem türü hem de değeri yazdırır.

Tür Kontrolcüsü Metodunu Kullanma

Tim, TürKontrolcüsü metodunu farklı türdeki argümanlarla çağırmanın örneklerini sunar.

TypeChecker(1); // Type: System.Int32, Value: 1
TypeChecker("Tim"); // Type: System.String, Value: Tim
TypeChecker(1.1); // Type: System.Double, Value: 1.1
TypeChecker(1); // Type: System.Int32, Value: 1
TypeChecker("Tim"); // Type: System.String, Value: Tim
TypeChecker(1.1); // Type: System.Double, Value: 1.1

TürKontrolcüsü metoduna çeşitli türler gönderen Tim, generics'in farklı veri türlerini sorunsuz bir şekilde nasıl işleyebileceğini gösterir.

Genel Bir Sınıf Oluşturma: Daha İyi Liste

Tim 16:25'te BetterList adında bir generic sınıf oluşturmaya geçiyor. Bu sınıf belirli bir türün listesini kapsar ve ek işlevsellik sağlar.

public class BetterList<t>
{
    private List<t> data = new List<t>();

    public void AddToList(T value)
    {
        data.Add(value);
        Console.WriteLine($"{value} has been added to the list");
    }
}
public class BetterList<t>
{
    private List<t> data = new List<t>();

    public void AddToList(T value)
    {
        data.Add(value);
        Console.WriteLine($"{value} has been added to the list");
    }
}

BetterList sınıfı, özel bir List ve listeye bir değer eklerken eklemeyi belirten bir mesaj yazdıran bir AddToList yöntemi içerir.

Better List Sınıfını Kullanma

Tim, BetterList sınıfını farklı türlerle kullanmanın örneklerini sunar.

BetterList<int> betterNumbers = new BetterList<int>();
betterNumbers.AddToList(5);

BetterList<PersonRecord> people = new BetterList<PersonRecord>();
people.AddToList(new PersonRecord("Tim", "Corey"));
BetterList<int> betterNumbers = new BetterList<int>();
betterNumbers.AddToList(5);

BetterList<PersonRecord> people = new BetterList<PersonRecord>();
people.AddToList(new PersonRecord("Tim", "Corey"));

Bu örneklerde BetterList, tamsayıların bir listesini yönetirken, BetterListPersonRecord nesnelerinin bir listesini yönetir. Listeye her ekleme, eklenen değeri belirten bir konsol mesajı tetikler.

Generic Arayüz Oluşturma

Tim, 21:48'de IImportance adında bir generic arayüz fikrini tanıtıyor. Bu arayüz, iki değerden hangisinin daha önemli olduğunu belirlemek için bir yöntem tanımlar.

public interface IImportance<t>
{
    T MostImportant(T a, T b);
}
public interface IImportance<t>
{
    T MostImportant(T a, T b);
}

Generic Arayüzü Uygulama

Tim, bu arayüzü farklı türlerde nasıl uygulayabileceğini gösteriyor. Öncelikle tamsayılar için bir uygulama ile başlıyor.

public class EvaluateImportance : IImportance<int>
{
    public int MostImportant(int a, int b)
    {
        return a > b ? a : b;
    }
}
public class EvaluateImportance : IImportance<int>
{
    public int MostImportant(int a, int b)
    {
        return a > b ? a : b;
    }
}

Sonra, önemini belirlemek için dize uzunluğunu kullanarak dize uygulamasını gerçekleştiriyor.

public class EvaluateStringImportance : IImportance<string>
{
    public string MostImportant(string a, string b)
    {
        return a.Length > b.Length ? a : b;
    }
}
public class EvaluateStringImportance : IImportance<string>
{
    public string MostImportant(string a, string b)
    {
        return a.Length > b.Length ? a : b;
    }
}

Bu uygulamalar, aynı arayüzün her tür için belirli bir mantıkla farklı türlere nasıl uygulanabileceğini gösterir.

Generic'lere Kısıtlamalar Uygulama

Tim 25:21'de generiklere kısıtlamalar nasıl uygulanacağını, belirli koşulları karşılamalarını sağlayacak şekilde açıklar. Örneğin, bir generic türün boş bir yapıcıya sahip olması veya belirli bir arayüzü uygulaması kısıtlanabilir.

public class SampleClass<t> where T : new()
{
    // Class implementation
}

public class SampleClassWithInterface<t> where T : IImportance<t>
{
    // Class implementation
}
public class SampleClass<t> where T : new()
{
    // Class implementation
}

public class SampleClassWithInterface<t> where T : IImportance<t>
{
    // Class implementation
}

Bu kısıtlamalar, generic tipin gerekli kriterleri karşılamasını sağlamaya yardımcı olur, çalışma zamanı hatalarını önler ve tür güvenliğini artırır.

Microsoft'un INumber Uygulaması

Tim, Microsoft'un sayısal işlemleri kısıtlamak için INumber arayüzünü nasıl kullandığını tartışıyor. Bu, generic türler üzerinde toplama ve çıkarma gibi aritmetik işlemlere izin verir.

public class MathOperations<t> where T : INumber<t>
{
    public T Add(T x, T y)
    {
        return x + y;
    }
}
public class MathOperations<t> where T : INumber<t>
{
    public T Add(T x, T y)
    {
        return x + y;
    }
}

Genel tür T'yi INumber ile kısıtlayarak, türün sayısal işlemleri desteklediğini garanti eder.

Farklı Sayısal Türlerle Generikleri Kullanma

Tim 33:55'te MathOperations sınıfını genişleterek, generiklerin çift ve ondalık gibi farklı sayısal türler ile nasıl kullanılabileceğini gösterir.

Tim, tamsayılar ve çiftler için MathOperations örneklerinin nasıl oluşturulacağını gösterir:

MathOperations<int> intMath = new MathOperations<int>();
Console.WriteLine(intMath.Add(1, 4)); // Outputs: 5

MathOperations<double> doubleMath = new MathOperations<double>();
Console.WriteLine(doubleMath.Add(1.5, 4.3)); // Outputs: 5.8
MathOperations<int> intMath = new MathOperations<int>();
Console.WriteLine(intMath.Add(1, 4)); // Outputs: 5

MathOperations<double> doubleMath = new MathOperations<double>();
Console.WriteLine(doubleMath.Add(1.5, 4.3)); // Outputs: 5.8

Bu, generiklerin esnekliğini, farklı sayısal türleri aynı sınıfta sorunsuz bir şekilde ele alabilme yeteneğini gösterir.

Farklı Sayısal Türleri Ele Alma

Tim, tür güvenliğinin önemine değinir ve farklı sayısal türlerin karıştırılamayacağını gösterir. Örneğin, bir çift ve tamsayıyı toplama girişimi derleme zamanı hatasına neden olur.

// This will result in a compile-time error
// Console.WriteLine(intMath.Add(1.5, 4));
// This will result in a compile-time error
// Console.WriteLine(intMath.Add(1.5, 4));

Tür Dönüşüm Yükünü Önleme

Tim, tür dönüşümü ile ilişkilendirilen yükten kaçınmak için generiklerin kullanımının avantajlarını açıklar. Örneğin, tamsayıları matematiksel işlemler için çiftlere dönüştürmek ve sonra tekrar tamsayılara dönüştürmek maliyetli olabilir. Generikler kullanarak, yerel türler üzerinde doğrudan işlemler yapılabilir, performans ve hassasiyet korunur.

Pratikte Generikler

Tim, generiklerin kullanımı konusunda dikkatli olmayı önerir, geliştiricilere onları uygun şekilde kullanmalarını ve aşırı kullanımından kaçınmalarını tavsiye eder. Generiklerin tür güvenliği, boxing ve unboxing azaltılması, derleme zamanı denetimi ve kod okunabilirliğinin artırılması gibi faydalarına vurgu yapar.

Generics'in, List ve Dictionary<TKey, TValue> gibi koleksiyonlarda yaygın olduğuna ve belirli ayrıntıları önceden bilmeden çeşitli türleri işleme gereken günlük çerçevelerde de kullanıldığına dikkat çeker.

Sonuç

Tim Corey'nin C#'ta ileri seviye generiklerle ilgili detaylı keşfi pratik uygulamalar ve faydalı kavrayışlar sağlar. Generikleri daha iyi anlamak ve gerçek dünyadaki örnekleri aksiyon halinde görmek istiyorsanız, Tim Corey'nin C# Generics hakkındaki detaylı videosunu izlemeyi unutmayın. Açık açıklamaları ve uygulamalı gösterimleri, kavramları tam olarak kavramanızı ve kendi projelerinizde etkili bir şekilde uygulamanızı sağlayacaktır.

Hero Worlddot related to C# Genellikleri (Generics) Uzmanlaşma
Hero Affiliate related to C# Genellikleri (Generics) Uzmanlaşma

Sevdiğiniz Şeyleri Paylaşarak Daha Fazla Kazanın

.NET, C#, Java, Python veya Node.js üzerinde çalışan geliştiriciler için içerik oluşturuyor musunuz? Uzmanlığınızı ek gelire dönüştürün!

Iron Destek Ekibi

Haftanın 5 günü, 24 saat çevrimiçiyiz.
Sohbet
E-posta
Beni Ara