您能否使用List <t>?</t> </t>来满足IEnumerable <t>的接口

时间:2013-09-28 16:17:32

标签: c# inheritance

假设我有以下模型:

public interface IProduct
{
    IEnumerable<Ingredient> Ingredients { get; set; }
}

public class Product : IProduct
{
    public IEnumerable<Ingredient> Ingredients { get; set; }
}

public class Ingredient
{
}

但我希望Ingredients成为List<Ingredient>而不是IEnumerable<Ingredient>

有没有办法对接口建模以接受IEnumerable<T>List<T>

我尝试了以下内容。但是,当然,语法不支持此功能,并且不会将TEnumerable<Ingredient>视为通用参数。

public interface IProduct<TEnumerable<Ingredient>> 
    where TEnumerable<Ingredient> : IEnumerable<Ingredient>
{
    TEnumerable<Ingredient> Ingredients { get; set; }
}

public class Product : IProduct
{
    public List<Ingredient> Ingredients { get; set; }
}

public class Ingredient
{
}

我意识到这不是很实用,但我只是怀着好奇心看着这个。

2 个答案:

答案 0 :(得分:4)

你的语法有点不对:

  • 您不能以通用的方式声明类型参数
  • 您的Product类型在说明如何实施IProduct<TEnumerable>
  • 时需要指定类型参数

所以这是有效的:

public interface IProduct<TEnumerable> 
    where TEnumerable : IEnumerable<Ingredient>
{
    TEnumerable Ingredients { get; set; }
}

public class Product : IProduct<List<Ingredient>>
{
    public List<Ingredient> Ingredients { get; set; }
}

它可能不是有用的,但至少它是有效的......

答案 1 :(得分:2)

您是否有兴趣在内部使用IProduct使用List<>,或者有兴趣在某些实现中展示List<>而在另一个实现中展示IEnumerable

如果是前者,则无需执行任何操作 - List<T>实施IEnumerable<T>,因此如果Product有内部List<Ingredient>,则只需将其返回作为IEnumerable<Ingredient>

public class Product : IProduct
{
   private List<Ingredient> _ingredients;
   public IEnumerable<Ingredient> Ingredients { get { return _ingredients; } }
}

但是,如果您对第二个选项(Jon Skeet的答案为您修复)感兴趣,我将不得不问您为什么要这样,因为它主要使界面更难以消费 - 而不是拥有所有呼叫者都遵守的统一合同,您有一个通用的元接口,不同的呼叫者使用不同的接口。这是一个有趣的概念,但如果您想要做的就是用IList替换IEnumerable,这似乎有些过分。