C# 我能否满足具有兼容返回类型的接口?
我有以下代码片段C# 我能否满足具有兼容返回类型的接口?,c#,covariance,C#,Covariance,我有以下代码片段 using System.Collections.Generic; public interface IInventoryItem {} public class InventoryItem : IInventoryItem {} public interface IInventory { IEnumerable<IInventoryItem> Items { get; } } public class Inventory : IInvent
using System.Collections.Generic;
public interface IInventoryItem {}
public class InventoryItem : IInventoryItem {}
public interface IInventory
{
IEnumerable<IInventoryItem> Items { get; }
}
public class Inventory : IInventory
{
public IEnumerable<InventoryItem> Items => items;
// IEnumerable<IInventoryItem> IInventory.Items => items;
private InventoryItem[] items = new InventoryItem[0];
}
使用System.Collections.Generic;
公共接口IInventoryItem{}
公共类清单项:IInventoryItem{}
公共接口库
{
IEnumerable项{get;}
}
公共类库存:投资
{
公共IEnumerable项=>项;
//IEnumerable IInventory.Items=>Items;
私有库存项[]项=新库存项[0];
}
我得到以下错误消息:
错误CS0738:Inventory
未实现接口成员IInventory.Items.get
和最佳实现候选Inventory.Items.get
返回类型System.Collections.Generic.IEnumerable
与接口成员返回类型System.Collections.Generic.IEnumerable
不匹配
添加IInventory.Items.get的显式实现确实是正确的,但为什么有必要呢
问题是:如果InventoryItem[]
是,为什么IEnumerable
不是IEnumerable
编辑:
关于为什么这很有趣:
我的假设:
Items.get
将始终返回有效的IEnumerable
这是必要的,因为IInventoryItem
是而不是(并且不能)仅限于由库存项实施
如果您(或任何其他人)将编写另一个实现IInventoryItem
接口的类,那么实现IInventoryItem
接口的任何类都将能够处理这个问题,因为它只处理IInventoryItem
接口,而不知道或关心具体的实现
如果编译器允许像您的问题中那样编写清单
类,那么它将无法处理实现IInventoryItem
接口的任何其他类
请澄清:
Items
属性返回一个IEnumerable
如果您添加了一个实现IInventoryItem
的不同类,并且该类不是从InventoryItem
继承的,则您的属性将无法返回它的IEnumerable
。
假设您添加了这个类:
public class MyNotRelatedInventoryItem : IInventoryItem
{ /* implementation here */ }
您当前的Items
属性将永远无法保存MyNotRelatedInventoryItem
的IEnumerable
,因为它与您的InventoryItem
类没有任何关系。除了Zohar已经提到的内容之外,下面是如何使用泛型实现您想要的:
public interface IInventoryItem {}
public class InventoryItem : IInventoryItem {}
public interface IInventory<T> where T : IInventoryItem
{
IEnumerable<T> Items { get; }
}
public class Inventory : IInventory<InventoryItem>
{
public IEnumerable<InventoryItem> Items => items;
private InventoryItem[] items = new InventoryItem[0];
}
您的属性返回类型与接口的不匹配,因此编译器不会将其视为接口实现。所以你需要把它改成
public IEnumerable<IInventoryItem> Items => items;
这是不可能的,下面的代码
public IEnumerable<IInventoryItem> Items
{
get { return items; }
set { items = value; }
}
但是,如果数组不完全由InvetoryItem
对象组成,则可能会出现异常情况。撇开一般差异不谈,这一要求一直是这样的:如果接口说返回类型是object
,则不能用返回字符串的方法实现。重写时也是如此。如果要使用具体类型,为什么需要接口?接口将位于另一个程序集中,这就是我需要它们的原因。当有人告诉你将接口放在任何地方都是因为它很好时,就会发生这种情况。它最终被滥用了,一张赞成票,两张反对票。我当然想知道我的答案有什么问题……我没有投反对票,但似乎你认为一些接口知道实现,但他们不知道。这并没有回答OP的问题,为什么他不能在get中返回一个实现所需接口的具体类型。你能举例说明你的意思吗“把柄“在最后一句话里<代码>如果编译器允许像您的问题中那样编写Inventory类,那么它将无法处理实现IInventoryItem接口的任何其他类。
真正的原因在链接为duplicate的问题的答案中给出:这似乎是CLR的一个限制。当setter不在接口中时,它是否相关?@Steinbitglis不太相关,只是为了强调输出的隐式转换和输入的显式转换。吹毛求疵:属性不是函数,方法的返回类型不是其签名的一部分。
public IEnumerable<InventoryItem> Items => items;
public interface IInventory
{
IEnumerable<IInventoryItem> Items { get; set; }
}
public IEnumerable<IInventoryItem> Items
{
get { return items; }
set { items = value; }
}
public IEnumerable<IInventoryItem> Items
{
get { return items; }
set { items = (InventoryItem[])value; }
}