[英]Why can't I declare generic List<T> as return type for interface method?
[英]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對接受的答案的評論表明不應該這樣做。
我錯過了什么或這是這樣做的方式嗎?
因為即使Base
是Parent
的子類型,也不意味着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.