Ошибка компилятора С# 'Параметр должен быть безопасным для ввода. Недопустимая дисперсия. Параметр типа 'T' должен быть неизменно действительным для Expression‹TDelegate› '

Я хочу использовать свой интерфейс ковариантно (Интерфейс должен быть ковариантным), но компилятор выдает мне ошибку Ошибка компилятора c#: - 'Параметр должен быть безопасным для ввода. Недопустимая дисперсия. Параметр типа «T» должен быть неизменно действительным для «Выражения». Это мой код:

interface IRepository<out T> where T : BaseEntity
{
    IEnumerable<T> Find(Expression<Func<T, bool>> predicate);
    T FindById(Guid id);
}

person yo2011    schedule 17.06.2014    source источник


Ответы (1)


Вы объявили T как ковариантный (используя ключевое слово out), но вы не можете принимать ковариантные параметры:

(MSDN)

Как правило, параметр ковариантного типа можно использовать в качестве возвращаемого типа делегата, а параметры контравариантного типа можно использовать в качестве типов параметров. Для интерфейса параметры ковариантного типа могут использоваться в качестве возвращаемых типов методов интерфейса, а параметры контравариантного типа могут использоваться в качестве типов параметров методов интерфейса.

Func<T, bool> принимает Tаргумент и возвращает bool, нарушая это правило. Вы можете пометить его как контравариантный, но вы возвращаете T в следующей функции.

Вы можете попытаться превзойти его, взяв два параметра типа (один ковариантный и один контравариантный), например:

interface IRepository<out T, in U> where T : BaseEntity
                                   where U : BaseEntity
{
    IEnumerable<T> Find(Expression<Func<U, bool>> predicate);
    T FindById(Guid id);
}

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

person BradleyDotNET    schedule 17.06.2014
comment
Еще лучше, where U : T - person Ben Aaronson; 18.06.2014
comment
Здравствуйте, спасибо за вашу помощь; Есть ли способ добиться этого, поскольку у меня есть производные интерфейсы, которые реализуют IRepository‹out T›, такие как IPersonRepository:IRepository‹Person›, но когда у меня есть общая функция, которая принимает IRepository‹T› и передает IPersonRepository, я получаю ошибку компилятора - person yo2011; 18.06.2014
comment
@AhmedTolba Звучит как другой вопрос, и мне нужно увидеть реальный код, чтобы понять, что вы сделали неправильно. Дисперсия может быть сложной, и ее легко испортить. Я бы задал новый вопрос с кодом, с которым у вас возникла проблема, и дал бы ссылку на этот, если он дает контекст. - person BradleyDotNET; 18.06.2014