考虑一个例子:

我有一个这样的界面.我需要这个接口是协变的——这意味着我必须将我的泛型声明为"out",并使用IEnumerable而不是list——仅此而已.我将使用它来简单地获取我需要的元素——无需插入任何内容.

    public interface IFoo<out T>
    {
          IEnumerable<T> Items { get; } 
    }

然后我让我的具体课程声明如下:

    public class Foo : IFoo<Item>
    {
         // I have an error here : Type IList doesn't match the expected type IEnmerable
          IList<Item> Items { get; set; } 
    }

我想知道为什么这不可能?我的意思是IList继承了IEnumerable,这种类型的代码工作得非常好.

public IEnumerable<Item> GetItems()
{
    return new List() { new Item())};
}

为什么可以这样做?解决办法是什么?

我唯一的解决方案是,我可以创建这样的附加属性或方法

public IEnumerable<Item> GetEnumerableItems()
{
   return Items;
}

但它对我来说太黑了.我想可能有一个更干净的解决方案.

推荐答案

运行时不支持这一点.如果实现的接口具有返回特定类型的属性,则必须在实现中完全匹配该返回类型.

在C#9中添加了Return Type Covariance,但不适用于此处(参见@Jeroenmoster的 comments ).

您可以通过使用显式接口实现来解决这个问题:

public class Foo : IFoo<Item>
{
    IList<Item> Items { get; set; }
    IEnumerable<Item> IFoo<Item>.Items => Items;
}

SharpLab

拥有Foo分的消费者可以访问Foo.Items分,获得IList<Item>分.只有IFoo<Item>的消费者可以访问IFoo<Item>.Items,并将获得IEnumerable<Item>.

.net相关问答推荐

将 Span 传递到函数时出现 F# 错误

问:在 Blazor WASM 应用程序中存储 api 密钥的最佳方式是什么?

当 Func 委托需要接口作为参数时,它是如何工作的?

SetupSet() 已过时.代替什么?

从 switch 块中跳出 foreach 循环

找不到 Microsoft.Office.Interop Visual Studio

如何将字符串列表数据绑定到 WPF/WP7 中的 ListBox?

SubscribeOn 和 ObserveOn 有什么区别

如何以编程方式 Select ListView 中的项目?

隐式与显式接口实现

检索字典值最佳实践

使用语句与最终try

如何使用 Entity Framework Code First CTP 5 存储图像?

无法加载文件或程序集Antlr3.Runtime (1)或其依赖项之一

为什么 double.NaN 不等于自身?

合并两个(或更多)PDF

如何使用 NPOI 读取文件

/langversion 的错误选项6无效;必须是 ISO-1、ISO-2、3、4、5 或默认值

如何为我的 C# 应用程序创建产品密钥?

Uri.Host 和 Uri.Authority 有什么区别