.net 4 вопрос о дженериках

У меня есть следующая структура класса:

public class A : AInterface { }
public interface AInterface { }

public class B<T> : BInterface<T> where T : AInterface 
{
    public T Element { get; set; }
}
public interface BInterface<T> where T : AInterface 
{
    T Element { get; set; }
}

public class Y : B<A> { }

public class Z<T> where T : BInterface<AInterface> {}

public class Test
{
    public Test()
    {
        Z<Y> z = new Z<Y>();
    }
}

Это дает мне следующую ошибку компиляции в С# 4.0. Тип «Test.Y» нельзя использовать в качестве параметра типа «T» в универсальном типе или методе «Test.Z». Неявное преобразование ссылок из «Test.Y» в «Test.BInterface» отсутствует.

Я думал, что ковариация в дженериках должна заставить это работать? Любая помощь будет оценена.


person roger    schedule 29.12.2009    source источник


Ответы (2)


Универсальные параметры в интерфейсах по умолчанию инвариантны, вам необходимо явно указать, хотите ли вы, чтобы конкретный универсальный параметр был ковариантным или контравариантным. По сути, в вашем примере вам нужно добавить ключевое слово «out» в объявление интерфейса:

public interface BInterface<out T> where T : AInterface { } 

Дополнительную информацию о создании вариантов интерфейсов можно найти в MSDN: Создание Варианты универсальных интерфейсов (C# и Visual Basic).

person Alexandra Rusina    schedule 29.12.2009
comment
Спасибо Александра. Это, безусловно, помогло бы, если бы T был возвращаемым параметром. В моем случае я упустил важную деталь в B и BInterface: public class B‹T› : BInterface‹T› где T : AInterface { public T Element { get; набор; } } открытый интерфейс BInterface‹T›, где T : AInterface { T Element { get; набор; } } out не будет работать, так как T является одновременно входом и выходом. Какие-либо предложения? - person roger; 29.12.2009
comment
Да, если у вас есть общее ограничение на параметр типа, вы не можете сделать его ковариантным. Это по дизайну. msdn.microsoft.com/en-us/library/dd469487 (VS.100).aspx В универсальном интерфейсе параметр типа может быть объявлен ковариантным, если он удовлетворяет следующим условиям: 1) Параметр типа используется только как возвращаемый тип методов интерфейса и не используется как тип аргументов метода. 2) Параметр типа не используется в качестве общего ограничения для методов интерфейса. - person Alexandra Rusina; 30.12.2009

Я думаю, что вы пропустили ключевое слово out. Попробуйте добавить его в следующие строки:

public interface BInterface<out T> where T : AInterface { }
public class Z<out T> where T : BInterface<AInterface> {}

Однако я не уверен, что это необходимо в обоих местах.

person Greg    schedule 29.12.2009
comment
Классы не могут быть вариантными, поэтому вы не можете добавлять или добавлять общие параметры в классах. - person Alexandra Rusina; 29.12.2009