Virtual dispatch
Sanal metot tablosu ve çalışma zamanı dağıtımını öğrenirsin.
Sanal metot tablosu (vtable)
Bir sınıf virtual metot içeriyorsa derleyici arkada bir sanal metot tablosu (vtable) oluşturur. Her nesne bu tabloya gizli bir başvuru taşır. virtual çağrıda derleyici doğrudan değil, dolaylı çağrı üretir: tablodan gerçek metodu bulur.
Bu yüzden runtime dispatch denir. Sanal çağrı, doğrudan çağrıdan biraz yavaştır; ama modern donanımda fark genellikle önemsizdir. Performans kritikse sealed override yazarak son türevi kilitler ve tablo aramasını bazen kısaltabilirsin.
sealed override ile kilitleme
Bir override metodun daha fazla geçersiz kılınmasını engellemek için başına sealed eklersin: public sealed override void Speak(). Bu, derleyiciye “bu sınıftan türetilenler artık bu metodu değiştiremez” demektir.
Sealed override hem güvenlik (yanlışlıkla değiştirmeyi önler) hem de bazen performans (vtable aramasını bazen atlar) sağlar. Aşırı kullanma: gerçekten gerekmedikçe sınıfları mühürlemek genişletilebilirliği azaltır. Soyut bir hiyerarşinin uç noktalarında mantıklıdır.
Uygulama Sanal dispatch ile hayvan sesleri
Animal sınıfında public virtual void Speak() metodu Console.WriteLine("Ses") yazsın. Dog : Animal sınıfında override ile Console.WriteLine("Hav") yazsın. Cat : Animal sınıfında override ile Console.WriteLine("Miyav") yazsın. Main içinde List<Animal> oluştur; içine Dog, Cat, Animal koy. foreach ile Speak çağır.
Örnek çözümü göster
Animal { public override void Speak() { Console.WriteLine("Hav"); } } ve class Cat : Animal { public override void Speak() { Console.WriteLine("Miyav"); } } yaz. Main'de List<Animal> { new Dog(), new Cat(), new Animal() } oluştur ve foreach ile Speak çağır.
Örnek çözüm:
using System;
using System.Collections.Generic;
class Animal
{
public virtual void Speak()
{
Console.WriteLine("Ses");
}
}
class Dog : Animal
{
public override void Speak()
{
Console.WriteLine("Hav");
}
}
class Cat : Animal
{
public override void Speak()
{
Console.WriteLine("Miyav");
}
}
class Program
{
static void Main()
{
var animals = new List<Animal> { new Dog(), new Cat(), new Animal() };
foreach (var a in animals)
{
a.Speak();
}
}
}
Kendini test et
-
Anahtar kelimeyi etkisine eşle
- virtual
- vtable girişi oluşturur
- override
- vtable girişini değiştirir
- new
- Yeni yuva oluşturur
- sealed
- Daha fazla değişimi engeller
-
Sanal dispatch ne zaman gerçekleşir?
Animal a = new Dog(); a.Speak();- Çalışma zamanında nesnenin türüne göre
- Derleme zamanında referans türüne göre
- Yalnızca sealed kullanılırsa
- Yalnızca new kullanılırsa
Cevabı göster
Çalışma zamanında nesnenin türüne göre — Doğru. Sanal dispatch runtime'da nesnenin gerçek türüne göre yapılır.
-
Geçersiz kılmayı kilitle
public ____ override void Speak() { }Cevabı göster
public sealed override void Speak() { }