Covariance ve Contravariance: Generic Tipler Arası Dönüşüm
C# dilinde generic tipler kullanırken, bir List<Hayvan> değişkenine List<Köpek> atayabilir misin? Cevap çoğu zaman hayır. bu noktada covariance ve contravariance devreye girer, kalıtım ilişkisini generic parametrelere taşıyan mekanizmalar.
Covariance, türetilmiş bir tipi temel tipmiş gibi davranmanı sağlar. Yalnızca okuma (çıktı) işlemleri için güvenlidir.
1public interface IRepository<out T>2{3T GetItem();4}56public class Hayvan { }7public class Köpek: Hayvan { }89public class KöpekRepository: IRepository<Köpek>10{11public Köpek GetItem() => new Köpek();12}1314var köpekRepo = new KöpekRepository();15IRepository<Hayvan> hayvanRepo = köpekRepo; // Covariance sayesinde çalışır16Hayvan sonuc = hayvanRepo.GetItem(); // Köpek döner, Hayvan olarak tutulurBurada out anahtar sözcüğü covariance'ı etkinleştirir. GetItem() yalnızca tip döndürdüğü için, Köpek yerine Hayvan istemek güvenlidir.
Contravariance bunun tersidir. Temel tipi türetilmiş tipmiş gibi kullanmayı sağlar. Yalnızca yazma (girdi) işlemleri için güvenlidir.
1public interface ILogger<in T>2{3void Log(T item);4}56public class UniversalLogger: ILogger<Hayvan>7{8public void Log(Hayvan item)9{10Console.WriteLine($"Hayvan logu: {item.GetType().Name}");11}12}1314var universalLogger = new UniversalLogger();15ILogger<Köpek> köpekLogger = universalLogger; // Contravariance sayesinde çalışır16köpekLogger.Log(new Köpek()); // Çıktı: Hayvan logu: KöpekBurada in anahtar sözcüğü contravariance'ı etkinleştirir. Metot yalnızca parametre aldığı için, Köpek yerine Hayvan kabul eden logger güvenlidir.
Covariance ve contravariance olmadan, kalıtım ilişkisi generic parametrelerde kaybolur ve kod yeniden kullanımı azalır. out ve in ile bu ilişkiyi koruyup tür güvenliğini de sağlarsın.
Pratik bir kural: veri çıkıyor mu out (covariance), veri giriyor mu in (contravariance). Her ikisine de ihtiyaç varsa, variance kullanmadan düz generic yazarsın.
0 yorum