IEnumerable Arayüzü- Read-Only
Bu özelliklik C# 4.0 ile geliyor. Covariant nesne geçmek istersek metodun imzasında IEnumerable olmalı. List olamaz!
Sebebi
IEnumerable covairant olduğu için covariant atama yapılabilir. Şöyle tanımlıdır. Buradaki out kelimesi covariant olduğunu belirtir.
List covariant değil. Şöyle tanımlıdır.
Örnek
Elimizde şöyle bir hiyerarşi olsun
Elimizde şöyle bir kod olsun.
Covariant nesne geçerken T tipinin class olduğu belirtilmeli. Şu kod derlenmez
Bu özelliklik C# 4.0 ile geliyor. Covariant nesne geçmek istersek metodun imzasında IEnumerable olmalı. List olamaz!
Sebebi
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
List SınıfıList covariant değil. Şöyle tanımlıdır.
public class List<T> : IList<T>, ... ...
Elimizde şöyle bir hiyerarşi olsun
abstract class Foo {}
class Bar : Foo {}
Foo tipinden liste alan bir metod olsunvoid AddEntries(List<Foo>) {}
Bu metoda Bar tipinden bir liste geçmek istersekList<Bar> barList = new List<Bar>()
AddEntries(barList);
Şu hatayı alırız.Şöyle yapmak gerekir.cannot convert from List<Bar> to List<Foo>
static void AddEntries(IEnumerable<Foo> entries)
ÖrnekElimizde şöyle bir kod olsun.
public interface IA { }
public interface IB : IA { }
public class CIA : IA { }
public class CIAD : CIA { }
public class CIB : IB { }
public class CIBD : CIB { }
Elimizde şöyle bir kod olsun. Metodun imzasında IEnumerable kullanılmış.private static void Something2(IEnumerable<IA> foo)
{
}
Şöyle yaparız.// All those calls are legal
Something2(new List<IA>());
Something2(new List<IB>());
Something2(new List<CIA>());
Something2(new List<CIAD>());
Something2(new List<CIB>());
Something2(new List<CIBD>());
Something2(bar.Cast<IA>());
Örnek
Covariant nesne geçerken T tipinin class olduğu belirtilmeli. Şu kod derlenmez
public static IList<T> Something<T>(IEnumerable<T> foo) where T : IA
{
var bar = foo.ToList();
// This call is illegal
Something2(bar);
return bar;
}
private static void Something2(IEnumerable<IA> foo)
{
}
Hata olarak şunu alırız.Argument 1: cannot convert from 'System.Collections.Generic.List<T>'
to 'System.Collections.Generic.IEnumerable<ConsoleApp20.Program.IA>'
Açıklaması şöyle....covariance only works on reference types.Düzeltmek için şöyle yaparız.
Now, you're probably saying "but IA is a reference type" right now. Yes, it is. But you didn't say that T is IA. You said that T is a type which implements IA, and a value type can implement an interface.
If you want covariance to work you have to tell the compiler that the type parameter is a reference type with the class constraint as well as the IA interface constraint.
The error message really should say that the conversion is not possible because covariance requires a guarantee of reference-type-ness, since that is the fundamental problem.
public static IList<T> Something<T>(IEnumerable<T> foo) where T : class, IA
Hiç yorum yok:
Yorum Gönder