Подтвердить что ты не робот

Недопустимая дисперсия: параметр типа "T" должен быть контравариантно действителен в "UserQuery.IItem <T>.ItemList". 'T' является ковариантным

Почему свойство получает ошибку при компиляции метода?

public interface IFoo {}
public interface IBar<out T> where T : IFoo {}

public interface IItem<out T> where T: IFoo
{
    // IEnumerable<IBar<T>> GetList(); // works
    IEnumerable<IBar<T>> ItemList { get; set; } // Error!
}

Ошибка:

Неверная дисперсия: параметр типа 'T' должен быть контравариантно действительным в 'UserQuery.IItem <T> .ItemList'. "T" ковариантно.

4b9b3361

Ответ 1

Вы получаете ошибку компилятора, потому что у вас есть свойство getter (get) и setter (set). У получателя свойства есть T в нем вывод, поэтому out работает, но у установщика свойств будет T на его входе, поэтому ему понадобится модификатор in.

Поскольку у вас есть out на T, вам нужно удалить установщик, и он скомпилирует:

public interface IItem<out T> where T : IFoo
{
    // IEnumerable<IBar<T>> GetList(); // works
    IEnumerable<IBar<T>> ItemList { get; } // also works
}

Если ваш T является общим аргументом in, тогда будет работать следующее:

public interface IItem<in T> where T : IFoo
{
    IEnumerable<IBar<T>> ItemList { set; } 
}

Но вы не можете одновременно использовать оба (out,in), чтобы не иметь свойство co/contravariant с геттером и сеттер.

Ответ 2

Установщик не разрешен, так как если бы вы могли это сделать:

public interface ISubFoo : IFoo { }

IItem<ISubFoo> item = //whatever
item.ItemList = new List<IBar<IFoo>>>();

который не является безопасным по типу.