#c_sharp #net #generics #компилятор
Зачем компилятор запрещает делать такие штуки как interface II{ void M () where V : T; } Хотя, если убрать ограничение where V : T, то компилятор позволит это скомпилировать И второй пример interface II { void M () where V : T; } class A : II { public void M ()// where V : T { throw new NotImplementedException(); } void II .M () { throw new NotImplementedException(); } } Тут если убрать в классе явную реализацию, то компилятору захочется поругаться на то, что нет ограничения в неявной реализации. Почему? Откуда растут ноги у таких запретов компилятора? Зачем их ввели (желательно на примере, где видно, что без них было бы хуже)?
Ответы
Ответ 1
Проблема со второй частью очевидна. Если у вас нет явной реализации, то метод public void M() должен реализовать интерфейсный метод void M () where V : T. Соответственно отсутствие ограничения будет нарушением. Для явной реализации интерфейса ограничения (неявно) применяются. т. к. вы не можете вызвать этот метод иначе, чем через интерфейс. Но для неявной реализации — то есть, обыкновенного метода, который можно вызывать напрямую — неявное применение ограничений было бы слишком непонятным для пользователей класса. По поводу первой части, сообщение об ошибке даёт нужную информацию: Invalid variance: The type parameter T must be contravariantly valid on II .M (). T is covariant. Смотрите, out-параметр T является ковариантным. То есть, II является подтипом II . Пусть у нас есть класс class C : II { void M () where V : Derived { } } Тогда мы можем написать: II ii = new C(); ii.M (); Но в объекте C у нас не может быть Base generic-параметром для M! То есть, как видите, where V : T подходит для контравариантных, но не ковариантных параметров, то есть, является контравариантным использованием.
Комментариев нет:
Отправить комментарий