22 Şubat 2018 Perşembe

Covariant Nesne Atama

Giriş
Açıklaması şöyle
Covariance: Enables you to use a more derived type than originally specified.
Covariant kalıtan sınıfın üst sınıf yerine kullanılabilmesi demek. Kavram kendi içinde covariant nesne atama ve covariant return type olarak ayrışmış durumda.

Covariance C# 4.0 ile geliyor ve array, delegate ve generic'lerle beraber kullanılıyor.

Dikkat!
Dikkat edilmesi gereken nokta covariant nesne atama adı üzerinde sadece reference tipler için kullanılır. Value tipler nesne olmadıkları için covariant nesne atama işlemine tabi tutulamazlar. Aşağıdaki kod int kullanıldığı derlenmez!
IEnumerable<int> intList = new List<int>();
IEnumerable<object> objList = intList;
Açıklaması şöyle.
Variance applies only to reference types; if you specify a value type for a variant type parameter, that type parameter is invariant for the resulting constructed type.
Covariance'tan Önceki Problem
Grandfather'dan kalıtan Son sınıfımız olsun. Eskiden "Grandfather" listesi'ne "Son" listesi atanamıyordu!
//will throw exception prior to version 4.01
IEnumerable<GrandFather> fathers = new List<Son>();
Diğer
Bazı sınıfların özellikleri şöyle

1. Array Sınıfı
Array covariant. Şöyle yaparız.
// Array assignment works
Animal[] animals = new Giraffe[10]; 
2. Delegate Sınıfı
Delegate covariant. Şöyle yaparız.
Func<string> stringFactory = () => "always return this string";
Func<object> objectFactory = stringFactory; // Safe, allowed in C# 4
3. ICollection Arayüzü
ICollection covariant değil. Şu kod derlenmez
IEnumerable<Animal> x = ViewModelList; // ok
ICollection<Animal> y = ViewModelList; // not ok.
4. IEnumerable Arayüzü- Read-Only
Bu özelliklik C# 4.0 ile geliyor. IEnumerable covairant olduğu için covariant atama yapılabilir. Şöyle tanımlıdır. Buradaki out kelimesi covariant olduğunu belirtir.
public interface IEnumerable<out T> : IEnumerable
Şöyle yaparız.
IEnumerable<Animal> animals = new List<Giraffe>();
// Can't add a Lion to animals, as `IEnumerable<out T>` is a read-only interface.
Eğer istersek daha okunur olduğunu düşünüyorsak casting kodu da eklenebilir. Şöyle yaparız.
// explicit casting
IEnumerable<Animal> animals = (IEnumerable<Animal>) new List<Giraffe>();
5. List Sınıfı
List covariant değil. Şöyle tanımlıdır.
public class List<T> : IList<T>, ... ...
Örnek 
Şu kod derlenmez.
List<Animal> animals = new List<Giraffe>();
Örnek 
Elimizde şöyle bir metod olsun
public Constructor (List<IData> data) { ... }
IData'dan kalıtan source sınıfımız olsun. Şu kod da derlenmez.
var a = new Constructor (new List<source> ()); This is failed
Çözüm
Listeyi çevirmek için şöyle yaparız. Bu aslında covariance değil. Yeni bir liste yaratıyor.
List<Giraffe> giraffes = new List<Giraffe>();
List<Animal> animals = giraffes.Cast<Animal>().ToList();
Çözüm
Bu kod çözüm 1'e göre daha kötü. .Net 2.0 ile çalışıyorken kullanılmalı.Şöyle yaparız.
List<Giraffe> giraffes = new List<Giraffe>();
List<Animal> animals = new List<Animal>(giraffes.ToArray());





Hiç yorum yok:

Yorum Gönder