Genel türlere genel bakış

Geliştiriciler, .NET'te açıkça veya örtülü olarak her zaman genel türler kullanır. .NET'te LINQ'i kullanırken, ile çalıştığına dikkat ettiniz IEnumerable<T> mi? Veya daha önce Entity Framework kullanarak veritabanlarıyla konuşmak için "genel bir depo" örneği görüyorsanız, çoğu yöntemin dönüş yaptığını mı IQueryable<T> görüyorsunuz? Bu örneklerde T'nin ne olduğunu ve neden orada olduğunu merak etmiş olabilir.

İlk olarak .NET Framework 2.0'da tanıtilen genel türler temelde geliştiricilerin gerçek bir veri türüne işlemeye gerek kalmadan türe uygun veri yapıları tanımlamalarını sağlayan bir "kod şablonudur". Örneğin, List<T> , veya gibi herhangi bir türle bildirilene ve kullanılan genel bir List<int> List<string> List<Person> koleksiyondur.

Genel türlerin neden yararlı olduğunu anlamak için, genel tür eklemeden önce ve ekledikten sonra belirli bir sınıfa göz at bakalım: ArrayList . 1.NET Framework 1.0'da ArrayList öğeleri Object türündedir. Koleksiyona eklenen herhangi bir öğe sessiz bir şekilde öğesine Object dönüştürüldu. Aynı durum, listeden öğeleri okurken de oluşur. Bu işlem, kutulama ve kutudan açma olarak bilinirve performansı etkiler. Ancak performans dışında, derleme zamanında listede yer alan verilerin türünü belirlemenin bir yolu yoktur ve bu da biraz hassas bir kod sağlar. Genel türler, her bir liste örneğinin içereceğini veri türünü tanımlayarak bu sorunu çözer. Örneğin, 'a yalnızca tamsayılar ekleyebilir ve List<int> yalnızca Kişi'yi 'ye List<Person> eklersiniz.

Genel türler çalışma zamanında da kullanılabilir. Çalışma zamanı, hangi tür veri yapısını kullanmakta olduğunu bilir ve bellekte daha verimli bir şekilde depolar.

Aşağıdaki örnek, çalışma zamanında veri yapısı türünü öğrenmenin verimliliğini gösteren küçük bir programdır:

  using System;
  using System.Collections;
  using System.Collections.Generic;
  using System.Diagnostics;

  namespace GenericsExample {
    class Program {
      static void Main(string[] args) {
        //generic list
        List<int> ListGeneric = new List<int> { 5, 9, 1, 4 };
        //non-generic list
        ArrayList ListNonGeneric = new ArrayList { 5, 9, 1, 4 };
        // timer for generic list sort
        Stopwatch s = Stopwatch.StartNew();
        ListGeneric.Sort();
        s.Stop();
        Console.WriteLine($"Generic Sort: {ListGeneric}  \n Time taken: {s.Elapsed.TotalMilliseconds}ms");

        //timer for non-generic list sort
        Stopwatch s2 = Stopwatch.StartNew();
        ListNonGeneric.Sort();
        s2.Stop();
        Console.WriteLine($"Non-Generic Sort: {ListNonGeneric}  \n Time taken: {s2.Elapsed.TotalMilliseconds}ms");
        Console.ReadLine();
      }
    }
  }

Bu program aşağıdakine benzer bir çıktı üretir:

Generic Sort: System.Collections.Generic.List`1[System.Int32]
 Time taken: 0.0034ms
Non-Generic Sort: System.Collections.ArrayList
 Time taken: 0.2592ms

Burada, genel listeyi sıralamanın, genel olmayan listeyi sıralamaya göre önemli ölçüde daha hızlı olduğunu farkebilirsiniz. Genel olmayan listenin türü genelleştirilmişken, genel listenin türünün ayrı ([System.Int32]) olduğunu da farkebilirsiniz. Çalışma zamanı genel türünün olduğunu bildiği için, liste öğelerini bellekte temel tamsayı dizisinde depolar, genel olmayan öğenin ise her bir liste öğesini bir nesnesine List<int> Int32 ArrayList attırır. Bu örnekte de olduğu gibi, ek türler zaman alır ve liste sıralamayı yavaşlattır.

Çalışma zamanının genel türlerinizi öğrenmenin ek bir avantajı, daha iyi bir hata ayıklama deneyimidir. C# içinde genel bir öğede hata ayıklarken, veri yapınıza her öğenin türünü bilirsiniz. Genel türler olmadan, her bir öğenin türünü asla öğrenesiniz.

Ayrıca bkz.