Genel Sınıflar (C# Programlama Kılavuzu)

Genel sınıflar, belirli bir veri türüne özgü olmayan işlemleri kapsüller. Genel sınıflar için en yaygın kullanım, bağlantılı listeler, karma tablolar, yığınlar, kuyruklar, ağaçlar gibi koleksiyonlarla kullanılır. Koleksiyona öğe ekleme ve koleksiyondan öğe kaldırma gibi işlemler, depolanan veri türüne bakılmaksızın temelde aynı şekilde gerçekleştirilir.

Koleksiyon sınıfları gerektiren çoğu senaryo için önerilen yaklaşım.NET sınıf kitaplığında sağlananları kullanmaktır. Bu sınıfları kullanma hakkında daha fazla bilgi için bkz. .NET'te Genel Koleksiyonlar.

Genellikle, mevcut somut bir sınıfla başlayıp genelleştirme ve kullanılabilirlik açısından en uygun dengeye ulaşana kadar türleri birer birer tür parametrelerine dönüştürerek genel sınıflar oluşturursunuz. Kendi genel sınıflarınızı oluştururken dikkat edilmesi gereken önemli noktalar şunlardır:

  • Tür parametrelerine genelleştirebileceğiniz türler.

    Kural olarak, ne kadar çok tür parametreleştirebilirseniz kodunuz o kadar esnek ve yeniden kullanılabilir hale gelir. Ancak, çok fazla genelleştirme diğer geliştiricilerin okuması veya anlaması zor bir kod oluşturabilir.

  • Varsa tür parametrelerine uygulanacak kısıtlamalar (Bkz. Tür Parametrelerindeki Kısıtlamalar).

    İyi bir kural, işlemeniz gereken türleri işlemenize izin verecek mümkün olan en yüksek kısıtlamaları uygulamaktır. Örneğin, genel sınıfınızın yalnızca başvuru türleriyle kullanılmak üzere tasarlandığını biliyorsanız, sınıf kısıtlamasını uygulayın. Bu, sınıfınızın değer türleriyle istenmeyen kullanımını engeller ve üzerinde Tişlecini as kullanmanıza ve null değerleri denetlemenize olanak tanır.

  • Genel davranışın temel sınıflara ve alt sınıflara dahil edilip edilmeyeceği.

    Genel sınıflar temel sınıflar olarak hizmet ettiğinden, burada genel olmayan sınıflarla aynı tasarım konuları geçerlidir. Bu konunun devamında genel temel sınıflardan devralma ile ilgili kurallara bakın.

  • Bir veya daha fazla genel arabirim uygulanıp uygulanmayacağı.

    Örneğin, generics tabanlı bir koleksiyonda öğe oluşturmak için kullanılacak bir sınıf tasarlarsanız, sınıfınızın türünün nerede T olduğu gibi IComparable<T> bir arabirim uygulamanız gerekebilir.

Basit bir genel sınıf örneği için bkz. Genel Türlere Giriş.

Tür parametrelerinin ve kısıtlamalarının kurallarının, özellikle devralma ve üye erişilebilirliği ile ilgili genel sınıf davranışı üzerinde çeşitli etkileri vardır. Devam etmeden önce bazı terimleri anlamanız gerekir. Genel bir sınıf Node<T>, istemci kodu için, bir tür bağımsız değişkeni belirterek sınıfa başvurabilir - kapalı bir oluşturulmuş tür (Node<int> ) oluşturmak için veya tür parametresini belirtilmemiş bırakarak (örneğin, genel bir temel sınıf belirttiğinizde, açık bir oluşturulmuş tür (Node<T> ) oluşturmak için). Genel sınıflar somut, kapalı veya açık yapılı temel sınıflardan devralabilir:

class BaseNode { }
class BaseNodeGeneric<T> { }

// concrete type
class NodeConcrete<T> : BaseNode { }

//closed constructed type
class NodeClosed<T> : BaseNodeGeneric<int> { }

//open constructed type
class NodeOpen<T> : BaseNodeGeneric<T> { }

Genel olmayan, başka bir deyişle, somut sınıflar kapalı oluşturulmuş temel sınıflardan devralabilir, ancak açık oluşturulmuş sınıflardan veya tür parametrelerinden devralabilir, çünkü istemci kodunun temel sınıfın örneğini oluşturmak için gereken tür bağımsız değişkenini sağlamasının çalışma zamanında hiçbir yolu yoktur.

//No error
class Node1 : BaseNodeGeneric<int> { }

//Generates an error
//class Node2 : BaseNodeGeneric<T> {}

//Generates an error
//class Node3 : T {}

Açık oluşturulmuş türlerden devralan genel sınıfların, aşağıdaki kodda gösterildiği gibi devralan sınıf tarafından paylaşılmayan temel sınıf türü parametreleri için tür bağımsız değişkenleri sağlaması gerekir:

class BaseNodeMultiple<T, U> { }

//No error
class Node4<T> : BaseNodeMultiple<T, int> { }

//No error
class Node5<T, U> : BaseNodeMultiple<T, U> { }

//Generates an error
//class Node6<T> : BaseNodeMultiple<T, U> {}

Açık oluşturulmuş türlerden devralan genel sınıflar, temel türdeki kısıtlamaların üst kümesi olan veya olduğu anlamına gelen kısıtlamaları belirtmelidir:

class NodeItem<T> where T : System.IComparable<T>, new() { }
class SpecialNodeItem<T> : NodeItem<T> where T : System.IComparable<T>, new() { }

Genel türler aşağıdaki gibi birden çok tür parametresi ve kısıtlaması kullanabilir:

class SuperKeyType<K, V, U>
    where U : System.IComparable<U>
    where V : new()
{ }

Açık oluşturulan ve kapalı oluşturulan türler yöntem parametreleri olarak kullanılabilir:

void Swap<T>(List<T> list1, List<T> list2)
{
    //code to swap items
}

void Swap(List<int> list1, List<int> list2)
{
    //code to swap items
}

Genel bir sınıf bir arabirim uygularsa, bu sınıfın tüm örnekleri bu arabirime atanabilir.

Genel sınıflar sabit. Başka bir deyişle, bir giriş parametresi bir List<BaseClass>belirtirse, bir sağlamaya List<DerivedClass>çalışırsanız derleme zamanı hatası alırsınız.

Ayrıca bkz.