Ковариантность и контравариантность анонимных типов - PullRequest
0 голосов
/ 17 марта 2012

Я читал в C #, covariance and contravariance включить неявное преобразование ссылок для типов массивов, типов делегатов и аргументов универсальных типов.

Мне интересно, могу ли я использовать ковариацию и контрвариантность для анонимных типов (которыетипы классов являются производными непосредственно от объекта) и как это работает?

1 Ответ

7 голосов
/ 17 марта 2012

Можно ли использовать ковариацию и контравариантность универсальных интерфейсов и делегатов с анонимными типами?

Да.Анонимные типы ссылочные типы ;дисперсия работает только со ссылочными типами.

Как?

Ковариация интерфейса:

var sequenceOfAnonymous = from c in customers select new {c.Name, c.Age};
var sequenceOfObject = (IEnumerable<object>)sequenceOfAnonymous;

Ковариация массива:

var arrayOfAnonymous = sequenceOfAnonymous.ToArray();
var arrayOfObject = (object[]) arrayOfAnonymous;

Чтобы продемонстрировать ковариацию делегата, вам нужно использовать универсальный трюк вывода типа:

static Func<R> MakeFunc(Func<R> f) { return f; }
...
var funcOfAnonymous = MakeFunc( ()=>new { X = 123 } );
var funcOfObject = (Func<object>)funcOfAnonymous;

Для контраваризации интерфейса требуется немного другой прием: приведение примера:

interface IFrobber<in T> { void Frob(T t); }
class Frobber<T> : IFrobber<T> 
{ 
    public void Frob(T t) { Console.WriteLine(t); }
}
...
static IFrobber<T> FrobByExample<T>(IFrobber<T> frobber, T example) 
{ return frobber; }
...
var frobberOfObject = new Frobber<object>();
var frobberOfAnonymous = FrobByExample(frobberOfObject, new { X = 0 });

И аналогично для контраваризации делегата:

static Action<A> ActionByExample<A>(Action<A> action, A example) 
{ return action; }
...
var actionOfObject = (Action<object>) x => { Console.WriteLine(x); }
var actionOfAnonymous = ActionByExample(actionOfObject, new { X = 0 } );

Имеет смысл?

...