7 Kasım 2018 Çarşamba

Covariant Nesne Geçme

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.
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>, ... ...

Örnek
Elimizde şöyle bir hiyerarşi olsun
abstract class Foo {}
class Bar : Foo {}
Foo tipinden liste alan bir metod olsun
void AddEntries(List<Foo>) {}
Bu metoda Bar tipinden bir liste geçmek istersek
List<Bar> barList = new List<Bar>()
AddEntries(barList);
Şu hatayı alırız.
cannot convert from List<Bar> to List<Foo>
Şöyle yapmak gerekir.
static void AddEntries(IEnumerable<Foo> entries)
Örnek
Elimizde şö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.

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.
Düzeltmek için şöyle yaparız.
public static IList<T> Something<T>(IEnumerable<T> foo) where T : class, IA


Hiç yorum yok:

Yorum Gönder