C#中是否可以使用下界通配符?

时间:2019-08-28 10:03:21

标签: java c#

我是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);
}

1 个答案:

答案 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

上找到
相关问题