Aracılığıyla paylaş


Çalışma zamanındaki genel değerler (C# programlama kılavuzu)

Genel bir tür veya yöntem ortak ara dilde (CIL) derlendiğinde, bunu tür parametrelerine sahip olarak tanımlayan meta veriler içerir. Genel bir tür için CIL'nin nasıl kullanıldığı, sağlanan tür parametresinin bir değer türü mü yoksa başvuru türü mü olduğuna göre farklılık gösterir.

Genel bir tür, parametre olarak bir değer türüyle ilk kez oluşturulduğunda, çalışma zamanı, sağlanan parametre veya CIL'deki uygun konumlarda değiştirilen parametrelerle özel bir genel tür oluşturur. Özel genel türler, parametre olarak kullanılan her benzersiz değer türü için bir kez oluşturulur.

Örneğin, program kodunuzun tamsayılardan oluşan bir yığın bildirdiğini varsayalım:

Stack<int>? stack;

Bu noktada, çalışma zamanı, parametresinin yerine uygun bir tamsayı koyarak Stack<T> sınıfının özel bir sürümünü oluşturur. Artık program kodunuz bir tamsayı yığını kullandığında çalışma zamanı oluşturulan özel Stack<T> sınıfı yeniden kullanır. Aşağıdaki örnekte, bir tamsayı yığınının iki örneği oluşturulur ve kodun Stack<int> tek bir örneğini paylaşır:

Stack<int> stackOne = new Stack<int>();
Stack<int> stackTwo = new Stack<int>();

Ancak, parametresi olarak veya kullanıcı tanımlı bir yapı gibi Stack<T> farklı bir değer türüne sahip başka long bir sınıfın kodunuzun başka bir noktasında oluşturulduğunu varsayalım. Sonuç olarak, çalışma zamanı genel türün başka bir sürümünü oluşturur ve CIL'deki uygun yerlerde long ile değiştirir. Her özelleştirilmiş genel sınıf yerel olarak değer türünü içerdiğinden dönüştürmeler artık gerekli değildir.

Genel türler, başvuru türleri için biraz farklı çalışır. Genel bir tür herhangi bir referans türüyle ilk kez oluşturulduğunda, çalışma zamanı, CIL'deki parametrelerin yerine nesne referanslarının geçtiği özel bir genel tür oluşturur. Ardından, oluşturulan bir tür, parametresi olarak bir başvuru türüyle her seferinde başlatıldığında, ne tür olduğuna bakılmaksızın, çalışma zamanı genel türün daha önce oluşturulmuş özel sürümünü yeniden kullanır. Tüm başvurular aynı boyutta olduğundan bu mümkündür.

Örneğin, Customer sınıfı ve Order sınıfı olmak üzere iki başvuru türüne sahip olduğunuzu ve ayrıca Customer türlerinden oluşan bir yığın oluşturduğunuzu varsayalım:

class Customer { }
class Order { }
Stack<Customer> customers;

Bu noktada, çalışma zamanı verileri depolamak yerine daha sonra doldurulacak nesne başvurularını depolayan özelleştirilmiş bir Stack<T> sınıf sürümü oluşturur. Sonraki kod satırının adlı Orderbaşka bir başvuru türünden bir yığın oluşturduğunu varsayalım:

Stack<Order> orders = new Stack<Order>();

Değer türlerinden farklı olarak, Stack<T> türü için başka bir özelleştirilmiş Order sınıfı oluşturulmaz. Bunun yerine, sınıfın özelleştirilmiş sürümünün Stack<T> bir örneği oluşturulur ve orders değişkeni buna başvurmak için ayarlanır. Bir Customer türü yığını oluşturmak için bir kod satırıyla karşılaştığınızı varsayalım.

customers = new Stack<Customer>();

türü kullanılarak Stack<T> oluşturulan sınıfın Order önceki kullanımında olduğu gibi, özel Stack<T> sınıfın başka bir örneği oluşturulur. İçinde bulunan işaretçiler, bellekte türün boyutunda Customer bir alana başvuruda bulunacak şekilde ayarlanır. Başvuru türlerinin sayısı programdan programa büyük ölçüde farklılık gösterebileceğinden, genel türlerin C# uygulaması, derleyici tarafından başvuru türü genel sınıfları için oluşturulan özel sınıf sayısını bire indirerek kod miktarını büyük ölçüde azaltır.

Ayrıca, genel bir C# sınıfı bir değer türü veya başvuru türü parametresi kullanılarak örneklendiğinde, reflection çalışma zamanında onu sorgulayabilir ve hem gerçek türü hem de tür parametresi doğrulanabilir.

Ayrıca bakınız