我是Java开发人员,还学习C#和.Net。最近,我了解到Java中存在上限和下限通配符。
<? extends AbstractClass> // upper bounded wildcard
<? super ConcreteClass> // lower bounded wildcard
我尝试谷歌搜索答案,但我只读到关于变异的信息,这使我更加困惑。
在C#中是否可以做这样的事情?
public static void addCat(List<? super Cat> list) {
list.add(new Cat());
}
// ...
interface Pet {}
class Cat implements Pet {}
class Dog implements Pet {}
// ...
public static void main(String[] args) {
List<Pet> pets = new ArrayList<>();
pets.add(new Dog());
addCat(pets);
}
答案 0 :(得分:4)
C#还支持方差(协方差和逆方差),该方差与Java中的“上/下”通用范围密切相关。
但是,不可能进行某些类的变体。实际上,只有通用接口和通用委托类型支持方差。
为了将某些接口标记为协变(即,允许使用比原始接口更多的派生类型),您需要在其通用类型参数旁边使用out
关键字,如示例所示:
interface IPetHouse<out T> where T : IPet
{
T Pet { get; }
};
class CatHouse : IPetHouse<Cat>
{
public Cat Pet => new Cat();
}
class DogHouse : IPetHouse<Dog>
{
public Dog Pet => new Dog();
}
// 'out' keyword gives possibility to treat CatHouse and DogHouse as IPetHouse<IPet> since IPet is less derived type
var petHouses = new IPetHouse<IPet>[] {
new CatHouse(),
new DogHouse()
};
// Types are preserved, which you can check easily
petHouses.Select(ph => ph.Pet.GetType().Name); //outputs: Cat and Dog
另一方面,要将接口标记为 contravariant (即,使接口能够使用比最初指定的类型更通用(派生较少)的类型),则需要在下一步中使用in
关键字其通用类型参数,如示例所示:
interface IPetHouse<in T> where T : IPet
{
void AddPet(T pet);
};
class PetHouse : IPetHouse<IPet>
{
public void AddPet(IPet pet)
{
}
}
class CatHouse : IPetHouse<Cat>
{
public void AddPet(Cat pet)
{
}
}
// 'in' keyword gives possibility to treat PetHouse as a CatHouse, since Cat is more derived type
IPetHouse<IPet> petHouse = new PetHouse();
IPetHouse<Cat> catHouse = petHouse;
catHouse.AddPet(new Cat()); // requires Cat to be passed
更多信息可在官方MSDN page
上找到