Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/278.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 我能否满足具有兼容返回类型的接口?_C#_Covariance - Fatal编程技术网

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; }
}