[英]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()
{
}
}
協方差與子類型和泛型的相互作用有關。 由於您的程序不涉及泛型,因此它不是協方差的示例。
如果U
是V
的子類型(例如, U = Pear
, V = Fruit
),則如果G<U>
是G<V>
的子類型,則認為泛型G<T>
在T
是協變的 。 例如, IEnumerable<Pear>
是IEnumerable<Fruit>
的子類型:你可以從中獲取梨子的東西可以用來取得果實。
如果G
反轉子類型關系( G<V>
是G<U>
的子類型),則認為它在T
是逆變的。 例如, Action<Fruit>
是Action<Pear>
的子類型:你可以放入水果的東西可以用來放梨。
在您的示例中, ICarInterface
和Car
都沒有可以協變的類型參數。
具體來說,在C#中,如果T
標記為out
,則泛型類型在類型參數T
是協變的。 正是在逆變T
如果T
標有in
。
不,這不是真正的協方差。 這只是一個接口的實現。 具體來說,它是分配兼容性的一個例子。 因為Car
類實現了ICarInterface
接口,所以可以將Car
對象分配給ICarInterface
類型的變量。 更具體類型( Car
)的對象被分配給存儲區域以用於特定於較少類型( ICarInterface
),這可以起作用,因為這兩種類型是為了分配目的而兼容的。
協方差是一個稍微不同的東西。 如果類型關系保留了類型的排序(從更具體到更通用),則它是協變的。 例如, IEnumerable<T>
對於類型T
是協變的,因此它保留了IEnumerable<Vehicle>
(更通用)和IEnumerable<Car>
(更具體)類型的排序。 (在這個例子中,我們當然假設Car
是Vehicle
的子類)。
Eric Lippert寫了一篇很好的文章,區分了協方差和賦值兼容性 。 它有點技術性和理論性,但你一定要讀它。 我試着在這里進一步總結一下,我不會公平。
一個更容易理解的協方差的例子(至少在我看來)是返回型協方差。 這是派生類重寫基類方法返回更具體類型的地方。 例如:
abstract class Habitat
{
public abstract Animal ApexPredator();
}
class Savanna : Habitat
{
public override Lion ApexPredator()
{ ... }
}
class Ocean : Habitat
{
public override Shark ApexPredator()
{ ... }
}
在這個例子中,抽象類Habitat
有兩個具體的子類: Savanna
和Ocean
。 所有棲息地都有一個ApexPredator
,屬於Animal
類型。 但是在Savanna
物體中,頂點捕食者是Lion
,而在Ocean
物體中,頂點捕食者是Shark
。 這是合法和安全的,因為Lion
和Shark
都是Animal
的類型。
不幸的是,C#不支持返回類型協方差。 但是,它受到C ++(包括C ++ / CLI),Java和許多其他面向對象語言的支持。
這不是協方差的一個例子,它只是多態性的一個簡單例子。 在這里你可以找到協方差和多態之間的差異
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.