簡體   English   中英

與C#和接口的協方差

[英]Covariance with C# and Interfaces

在接口方面,我不清楚C#中Covariance的概念。 嚴格基於我下面的例子,這是協方差的一個例子,請描述原因或原因。

class Program
{
    static void Main()
    {
        ICarInterface car = new Car();
    }
}

interface ICarInterface
{
    void Start();
}

class Car : ICarInterface
{
    public void Start()
    {

    }
}

協方差與子類型和泛型的相互作用有關。 由於您的程序不涉及泛型,因此它不是協方差的示例。

如果UV的子類型(例如, U = PearV = Fruit ),則如果G<U>G<V>的子類型,則認為泛型G<T>T協變的 例如, IEnumerable<Pear>IEnumerable<Fruit>的子類型:你可以從中獲取梨子的東西可以用來取得果實。

如果G反轉子類型關系( G<V>G<U>的子類型),則認為它在T逆變的。 例如, Action<Fruit>Action<Pear>的子類型:你可以放入水果的東西可以用來放梨。

在您的示例中, ICarInterfaceCar都沒有可以協變的類型參數。

具體來說,在C#中,如果T標記為out ,則泛型類型在類型參數T是協變的。 正是在逆變T如果T標有in

不,這不是真正的協方差。 這只是一個接口的實現。 具體來說,它是分配兼容性的一個例子。 因為Car類實現了ICarInterface接口,所以可以將Car對象分配給ICarInterface類型的變量。 更具體類型( Car )的對象被分配給存儲區域以用於特定於較少類型( ICarInterface ),這可以起作用,因為這兩種類型是為了分配目的而兼容的。

協方差是一個稍微不同的東西。 如果類型關系保留了類型的排序(從更具體到更通用),則它是協變的。 例如, IEnumerable<T>對於類型T是協變的,因此它保留了IEnumerable<Vehicle> (更通用)和IEnumerable<Car> (更具體)類型的排序。 (在這個例子中,我們當然假設CarVehicle的子類)。

Eric Lippert寫了一篇很好的文章,區分了協方差和賦值兼容性 它有點技術性和理論性,但你一定要讀它。 我試着在這里進一步總結一下,我不會公平。


一個更容易理解的協方差的例子(至少在我看來)是返回型協方差。 這是派生類重寫基類方法返回更具體類型的地方。 例如:

abstract class Habitat
{
    public abstract Animal ApexPredator();
}

class Savanna : Habitat
{
    public override Lion ApexPredator()
    { ... }
}

class Ocean : Habitat
{
    public override Shark ApexPredator()
    { ... }
}

在這個例子中,抽象類Habitat有兩個具體的子類: SavannaOcean 所有棲息地都有一個ApexPredator ,屬於Animal類型。 但是在Savanna物體中,頂點捕食者是Lion ,而在Ocean物體中,頂點捕食者是Shark 這是合法和安全的,因為LionShark都是Animal的類型。

不幸的是,C#不支持返回類型協方差。 但是,它受到C ++(包括C ++ / CLI),Java和許多其他面向對象語言的支持。

以下是協方差的一些更具體的例子

這不是協方差的一個例子,它只是多態性的一個簡單例子。 在這里你可以找到協方差和多態之間的差異

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM