Ограничения компилятора в обобщениях

251
31 декабря 2017, 05:17

Зачем компилятор запрещает делать такие штуки как

interface II<out T>
{
    void M<V>() where V : T;
}

Хотя, если убрать ограничение where V : T, то компилятор позволит это скомпилировать

И второй пример

interface II<T>
{
    void M<V>() where V : T;
}
class A<T> : II<T>
{
    public void M<V>()// where V : T
    {
        throw new NotImplementedException();
    }
    void II<T>.M<V>()
    {
        throw new NotImplementedException();
    }
}

Тут если убрать в классе явную реализацию, то компилятору захочется поругаться на то, что нет ограничения в неявной реализации. Почему? Откуда растут ноги у таких запретов компилятора? Зачем их ввели (желательно на примере, где видно, что без них было бы хуже)?

Answer 1

Проблема со второй частью очевидна.

Если у вас нет явной реализации, то метод public void M<V>() должен реализовать интерфейсный метод void M<V>() where V : T. Соответственно отсутствие ограничения будет нарушением.

Для неявной реализации интерфейса ограничения (неявно) применяются. т. к. вы не можете вызвать этот метод иначе, чем через интерфейс. Но для явного метода, который можно вызывать напрямую, неявное применение ограничений было бы слишком непонятным для пользователей класса.

По поводу первой части, сообщение об ошибке даёт нужную информацию:

Invalid variance: The type parameter T must be contravariantly valid on II<T>.M<V>(). T is covariant.

Смотрите, out-параметр T является ковариантным. То есть, II<Derived> является подтипом II<Base>.

Пусть у нас есть класс

class C : II<Derived> { void M<V>() where V : Derived { } }

Тогда мы можем написать:

II<Base> ii = new C();
ii.M<Base>();

Но в объекте C у нас не может быть Base generic-параметром для M! То есть, как видите, where V : T подходит для контравариантных, но не ковариантных параметров, то есть, является контравариантным использованием.

READ ALSO
Интеграция исходников ZedGraph в проект

Интеграция исходников ZedGraph в проект

Пытаюсь использовать данный компонент в качестве части проекта чтобы исключить внешние библиотекиПодскажите как использовать сторонние...

299
Как в c# проверить цифровые подписи файла?

Как в c# проверить цифровые подписи файла?

Есть программа processhacker в ней есть такой разделВ этом разделе выводит инфу о процессе есть сертификат или нету его

257
Как в поток передать параметр?

Как в поток передать параметр?

Появилась необходимость передать в поток параметрКак правильно это сделать?

262
Написать скрипт [требует правки]

Написать скрипт [требует правки]

как написать на javascript функцию которая с помощью onclick для кнопки в html,будет выдавать какое то сообщение

298