C # 4.0 RC, Silverlight 4.0 RC Ковариантность - PullRequest
0 голосов
/ 01 апреля 2010

Я пытаюсь разработать приложение Silverlight 4 с использованием C # 4.0. У меня есть такой случай:

public class Foo<T> : IEnumerable<T>
{
    ....
}

В другом месте:

public class MyBaseType : MyInterface
{
    ...
}

И использование там, где у меня проблемы:

Foo<MyBaseType> aBunchOfStuff = new Foo<MyBaseType>();
Foo<MyInterface> moreGeneralStuff = myListOFStuff;

Теперь я считаю, что это было невозможно в C # 3.0, потому что универсальный тип был "инвариантным". Однако я думал, что это возможно в C # 4.0 благодаря новой ковариации для технологии генериков?

Насколько я понимаю, в C # 4.0 многие общие интерфейсы (например, IEnumerable) были модифицированы для поддержки дисперсии. В этом случае мой класс Foo нуждается в чем-то особенном, чтобы стать ковариантным?

И поддерживается ли ковариация в Silverlight 4 (RC)?

Ответы [ 2 ]

4 голосов
/ 01 апреля 2010

Чтобы указать, что параметр универсального типа интерфейса или делегата является ковариантным в T, необходимо указать ключевое слово out.

Однако в настоящее время это невозможно для классов. Я предлагаю создать интерфейс с ковариантным параметром универсального типа и позволить вашему классу реализовать его.

Что касается ковариантной поддержки в Silverlight 4: в бета-версии она не поддерживалась, мне нужно будет проверить, реализовали ли они ее в кандидате на релиз. Изменить: видимо, это так.

Edit2: Может возникнуть некоторая путаница относительно того, поддерживает ли SL4 совместную и контрвариантность для интерфейсов и делегатов, поскольку некоторые типы в BCL не имеют соответствующего набора модификаторов универсального типа (IEnumerable<T>, Action<T>, Func<T>, ...).

Silverlight 5 решает следующие проблемы: http://10rem.net/blog/2011/09/04/the-big-list-of-whats-new-or-improved-in-silverlight-5

Компилятор SL4 поддерживает , однако поддерживает модификаторы in и out. Следующие компилируется и работает как положено:

interface IFoo<out T>
{
    T Bar { get; }
}
interface IBar<in T>
{
    void Add(T value);
}
delegate void ContravariantAction<in T>(T value);
delegate T CovariantFunc<out T>();
1 голос
/ 01 апреля 2010

Ковариация поддерживается только для интерфейсов и делегатов:

public interface Foo<out T> { }
public class Bar<T> : Foo<T> { }

interface MyInterface { }
public class MyBase : MyInterface { }

Foo<MyBase> a = new Bar<MyBase>();
Foo<MyInterface> b = a;

Важным является ключ out на интерфейсе Foo.

...