Generics Nedir ?

Sosyal medyada paylaşın

Generics, C# dilinde kullanılan bir programlama teknolojisidir ve bu teknoloji sayesinde tip bağımsız kod yazmak mümkündür. Yani bir metot, sınıf veya yapı içerisinde kullanılan değişkenlerin veri türleri önceden belirlenmez ve çalışma zamanında belirlenir. Bu da kodun daha modüler ve esnek olmasını sağlar. Bu yazıyı okuyan herkes farkında olmadan en az bir kere Generics kullanmıştır. Nasıl mı ? Örnek verelim 🙂 SerializeField, GetComponent gibi fonksiyonlar istediğimiz tipteki bileşene ulaşmamızı sağlar, yani biz <> arasında hangi tipi verirsek o tipte bize geri dönüş sağlar böylece ek uğraş olmadan işlerimizi kolayca halledebiliriz.

Örnek olarak, bir liste yapısı düşünelim. Geleneksel olarak, bu liste yapısında tutulacak verilerin tipi önceden belirlenir ve sadece bu veri tipine uygun veriler bu listede tutulabilir. Ancak generics kullanarak, liste yapısı oluştururken hangi veri tipinin kullanılacağı belirtilmez. Bu sayede, farklı veri tipleri kullanarak birden fazla liste oluşturulabilir ve bu listeler aynı kod bloğu içerisinde kullanılabilir.

Özetle, generics programlamada tip bağımsız kod yazmamızı sağlayan bir teknolojidir. Bu sayede kodlar daha esnek, modüler hale gelir ve kod tekrarı azaltılır. Önce Unity’nin kendi verdiği örneği inceleyip sonra kendi örneklerime geçelim.

using UnityEngine;
using System.Collections;

public class SomeClass 
{
    //Here is a generic method. Notice the generic
    //type 'T'. This 'T' will be replaced at runtime
    //with an actual type. 
    public T GenericMethod<T>(T param)
    {
        return param;
    }
}

Genel olarak Generic fonksiyon yapısı yukarıda gördüğünüz gibi. Farkettiyseniz fonksiyon tipi olarak alışıla gelmiş int,float,vector3 gibi tipleri kullanmak yerine T anahtar kelimesini kullandık. Bu sayede çalışma zamanında istenilen tipe göre fonksiyon çalışabilmektedir.


private List<T> FindAllEnemiesByType<T>() where T : Enemy
       {
           List<T> enemyList = new List<T>();
           foreach (Enemy enemy in enemiesInScene)
           {
               if (enemy is T)
               {
                   enemyList.Add(enemy as T);
               }
           }
           return enemyList;
       }

Yukarıdaki örneği çok beğendiğim için bu siteden alıntıladım. Yukarıdaki kod Generics mantığını çok iyi anlatıyor. Öncelikle birden farklı tipte enemy modelimiz olsun herhangi bir işlem gereği herhangi bit tipteki enemy modeline erişmem gerekirse bu örnekteki gibi generic fonksiyon yazarak işin içinden daha hızlı ve maliyetsiz bir şekilde çıkabilirim aksi halde kaç adet enemy modelim varsa o kadar enemy tipinde fonksiyon yazmam gerekecekti buda bazı prensiplere aykırı oluyor.


Son olarak kendi kodumu açıklayıp bitireyim.

        internal T SelectObjectWithMouse<T>(Vector3 mousePos, LayerMask layer)
        {
            Ray ray = Camera.main.ScreenPointToRay(mousePos);

            if (Physics.Raycast(ray, out hit, range, layer))
                return hit.transform.gameObject.GetComponent<T>();
            else return default(T);
        }

Kendi RaycastUtility sınıfımı yazarken gördüğünüz gibi Generic fonksiyon yapısı kullandım. Bunun sebebi ise fonksiyonu çağırırken istediğim tipte component geri döndürmesini istememden kaynaklı. Gelin bir de bu fonksiyona çağrı yapılan satırı inceleyelim.

           MeshRenderer selectedObj = rayUtility.SelectObjectWithMouse<MeshRenderer>(Input.mousePosition, 1 << 8);

Örneğin raycast ile sahnedeki bir objeyi seçip rengini değiştireceğim, SelectObjectWithMouse Generic fonksiyonuna MeshRenderer tipini veriyorum ki bana direkt verdiğim tipleri döndürsün ve daha Getcomponent yapmadan işlemimi kısaltmış olarak halledeyim.

Gördüğünüz gibi, tekrar özetleyecek olursam Generic yapısı kod tekrarını önlemek, modüler yapı sağlamak gibi işlevler sağlar.