假设我有以下模型:
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
{
}
我意识到这不是很实用,但我只是怀着好奇心看着这个。
答案 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,这似乎有些过分。