Supporting both covariance and contravariance for a single type parameter [duplicate]

∥☆過路亽.° 提交于 2019-12-21 11:23:12

问题


Possible Duplicate:
Covariance and Contravariance on the same type argument

You can declare a generic type parameter as covariant by using the out keyword:

interface ICovariant<out R>

You can declare a generic type parameter as contravariant by using the in keyword:

interface IContravariant<in R>

And you can also support both for different type parameters:

interface IVariant<out R, in A>

So why can't you suport both for a single type parameter?


回答1:


So why can't you suport both for a single type parameter?

Keep in mind that an interface can only be covariant in a type parameter if that type parameter is output-safe and an interface can only be contravariant in a type parameter if that type parameter is input-safe.

The syntax out T says that T is a covariant type parameter.

The syntax in T says that T is a contravariant type parameter.

As T is a covariant type parameter, it is by definition input-unsafe.

As T is a contravariant type parameter, it is by definition output-unsafe.

Therefore, T is input-unsafe and output-unsafe.

Consequently, T is prohibited in input positions, and T is prohibited in output positions.

Therefore, T can not appear in input positions nor in any output positions on any methods specified by the interface.

Consequently, T can not be used on the interface at all, and is pointless as a type parameter. Consequently, the language designers prohibit you from even including such a useless type marked as both covariant and contravariant on the interface to avoid the ugly

interface IFoo<in and out T> { }
Foo<T> : IFoo<T> { }

and then:

IFoo<Cat> cat = (IFoo<Animal>)new Foo<Dog>();

(If you need to read up on input-safe and output-safe, see 13.1.3.1 of the language specification.)




回答2:


It wouldn't work. Consider this (if in out existed):

public class INewList<in out T>
{
    public T DoIt(T item);
}

This would be impossible to satisfy because people expecting an INewList<T> would be compatible with interfaces with both narrower and wider types.

Consider INewList<Feline>:

If in/out both were possible, this interface would be equivalent to INewList<Animal> but this would be invalid for in positions because it would allow you to widen to type argument:

... DoIt(Animal item)

Which won't work because that would mean you could pass in a new Dog() instance where a Feline were expected from the original interface.

Similarly in reverse on the out positions because it would allow:

Puma DoIt(...)

Which would be invalid because the original interface could pass back any feline, not necessarily a Puma.



来源:https://stackoverflow.com/questions/6709148/supporting-both-covariance-and-contravariance-for-a-single-type-parameter

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!