所以我认为我的实现可能过于复杂,但这就是我正在做的事情:
现在我的问题是,在我的程序中,当我想使用List items = repository.Items.List();它不会编译,因为在ItemsTable中ITable的实现返回IList而不是List。我可以返回IList,但我确实希望使用具体的项目列表。
我能做得更好吗?
public interface ITable
{
IList<IItem> List();
bool Add(IItem item);
bool Delete(long itemId);
bool Find(long itemId);
}
public class ItemsTable : ITable
{
public IList<IItem> List()
{
IList<IItem> items = GetItems(); // GetItems return List<Item>, Item implements IItem.
return items;
}
.....
...
..
}
public class SQLRepository : IRepository
{
ITable items = new ItemsTable();
public ITable Items
{
get { return items; }
}
}
static void Main(string[] args)
{
var repository = new SQLRepository();
List<Item> items = repository.Items.List();
}
答案 0 :(得分:1)
我有几条评论。
首先,只是因为您定义了映射到您的具体类的接口,您无需在任何地方使用接口。使用您正在使用的接口列表的目的是限制存储库和对象的用户可以使用的表面区域。因此,请随时返回List<T>
而不是IList<T>
。
其次&amp;但是,返回实现IList<T>
的任何内容意味着您希望在从存储库中获取列表后修改列表的内容。由于种种原因,现在这样做可能是坏事和坏事。
如果您的存储库保留对它返回的列表的引用,那么后续调用者可以获取您修改的列表 - 因此您实际上无法保留引用。所以你需要为每次调用建立列表。
如果您为每个调用构建列表,那么在返回结果之前,您实际上正在调用.ToList
运算符。
另一种方法是允许来电者决定何时拨打.ToList
,然后您就可以返回IEnumerable<T>
。
现在这在很多方面都比较好。
它允许调用代码知道列表未被修改为另一个调用者。它还允许列表为列表的每个新迭代重新查询。
所以,我的建议是 - 不要返回IList<T>
或List<T>
- 返回IEnumerable<T>
,让来电者拨打.ToList()
。
答案 1 :(得分:0)
最好将您的界面更改为:
public interface ITable<TItem>
where TItem : IItem
{
IList<TItem> List();
bool Add(TItem item);
bool Delete(long itemId);
bool Find(long itemId);
}
答案 2 :(得分:0)
现在我的问题是,在我的程序中,当我想使用List items = repository.Items.List();它不会编译,因为在ItemsTable中ITable的实现返回IList而不是List。我可以返回IList,但我确实希望使用具体的项目列表。
好。你不能两者兼得。如果您想使用List<T>
,则需要返回一个。您无法创建一个合同,表明任何IList<T>
实施都可以,然后期望返回List<T>
。
由于IList<IItem> List();
承诺一件事,并且你希望它能提供其他东西,这些违规行为通常会在未来造成混乱。这就像去加油站订购无铅汽油并期望含铅气体(它仍然是天然气,但有点引导)。
答案 3 :(得分:0)
.NET的泛型集合没有任何差异。
显式实现接口方法,并提供返回具体列表的重载:
public MyTable : ITable
{
IList<IItem>ITable List()
{
return List().OfType<IItem>().ToList();
}
public List<MyItem> List()
{
var l = new List<MyItem>();
...
return l;
}
}