簡體   English   中英

為什么方法不能聲明返回類型`List <IMyInterface>`並返回實現它的具體類

[英]Why can't a method declare return type `List<IMyInterface>` and return a concrete class implementing it

我有以下界面

public interface IMyInterface
{
    // Some method and property signatures
}

我有以下類實現上面的接口

public class MyClass : IMyInterface
{
    // Some methods and properties as declared by IMyInterface
}

然后我在一些隨機類中有這個方法,我想返回一個實現IMyInterface的對象列表。 在這個特定的實現中,這些對象是MyClass實例。

public List<IMyInterface> getItems(int id)
{
    return new List<MyClass>();
}

這將導致編譯錯誤(在Visual Studio中也可實時顯示)

無法將類型'System.Collections.Generic.List <MyClass>'隱式轉換為'System.Collections.Generic.List <IMyInterface>'

我搜索了互聯網,最后找到了這個線程C#接口和通用列表 ,然后我最終得到了以下方法

public List<IMyInterface> getItems(int id)
{
    return new List<MyClass>().Cast<IMyInterface>().ToList();
}

這將編譯,但對我來說,處理它似乎是一種非常奇怪的方式; 將具體類轉換為接口。 在線程C#接口和通用列表 Aequitarum Custos對接受的答案的評論表明不應該這樣做。

我錯過了什么或這是這樣做的方式嗎?

因為即使BaseParent的子類型,也不意味着List<Base>List<Parent>的子類型。 IList<T>在其泛型參數中是不變的,因此List<T> (c#不支持類方差,只支持接口方差)。

閱讀更多關於協方差,逆變和不變性的信息: http//blogs.msdn.com/b/csharpfaq/archive/2010/02/16/covariance-and-contravariance-faq.aspx

如果List<T>是協變的,那么你被允許這樣做:

List<Parent> list = new List<Base>();

如果你這樣做會怎么樣?

list.Add(new OtherBase());

這在編譯時肯定是合法的,但會導致運行時錯誤。

這是因為List<T> T參數不是協變的 但它在IEnumerable<out T>

出來

要枚舉的對象的類型。

此類型參數是協變的。 也就是說,您可以使用指定的類型或更多派生的類型。

如果您考慮更改getItems簽名,那么您可以這樣做:

public IEnumerable<IMyInterface> getItems(int id)
{
    return new List<MyClass>() as IEnumerable<IMyInterface>;
}

您可以在此處找到有關協方差逆變的更多信息。

考慮這個例子:

public interface IAnimal
{
}

public class Cat : IAnimal
{
}

public class Dog : IAnimal
{
}

而你等效的方法:

public List<IAnimal> getAnimals()
{
    return new List<Dog>();
}


// You just Dog'd a list of Cats
IEnumerable<Cat> cats = getAnimals();

暫無
暫無

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

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