IEnumerable与List在具体类实现中的对比
本文关键字:实现 List IEnumerable | 更新日期: 2023-09-27 18:06:45
我正在写一个金融建模类库。
我想使用接口来定义模型,以创建用于测试的抽象,以及以后可能添加的新的具体类。
我正在努力定义事物的列表,所以我可以稍后在具体类中添加这些列表。
例如,如果我定义一个接口,在我的模型中有一个名为
的费用列表IEnumerable Expenses {get;设置;}
,然后想要创建一个名为ABCModel的具体类,其中包含一个具体的XYZExpense列表,实现列表的最佳方法是什么,以便我可以轻松地向列表添加更多项?
我不能将List强制转换为IEnumerable。
例如:
public interface IFinancialModel
{
IEnumerable<IExpense> Expenses { get; }
IEnumerable<IRevenue> Revenue { get; }
IEnumerable<IAsset> Assets { get; }
IEnumerable<ILiability> Liabilities { get; }
}
我需要一个具体的类,叫做公共类FinancialModel: IFinancialModel
,并能够添加具体的项目。
我应该创建我自己的'Add'方法吗?理想情况下,我想利用内置的列表功能,而不是重新发明轮子。
这取决于您实际想要做什么。不建议使用List
或IList
属性,因为您可以使用它做任何事情(如Clear
, Add
等),而无需拥有类知道它。这不利于封装。你将无法在更改时做一些事情(如设置脏标志,删除更改的事件或执行验证)。
IEnumerable
是个不错的选择。
可以添加setter,但不应该使用通过引用设置的属性值。它可以是任何东西,比如Linq查询,甚至是数据库查询,这些都是您不想引用的。你只想要这些东西。(还要考虑到,来自外部的对集合的引用可以分配给其他实例,当它在那里被修改而在这里不应该被修改时,这会导致非常糟糕的副作用。)
// example implementation with a setter
private List<IExpense> expenses
public IEnumerable<IExpense> Expenses
{
get { return expenses; }
set { expenses = value.ToList(); }
}
或者你可以实现自己的Add
, AddRange
, Remove
或Clear
等方法。但是,如果主要用例是一次性设置所有项,则只能使用SetExpenses
方法,这与我之前展示的属性上的setter相同。您可以考虑在内部将其保留为数组
你要找的是IList<T>
。这个接口允许您公开列表,同时隐藏实际的列表实现。例如:
interface IFinancialModel {
IList<IExpense> Expenses { get; }
}
然后用一个满足你需要的列表来实现。例如:
class FinancialModel : IFinancialModel {
private IList<IExpense> _expenses = new List<IExpense>();
IList<IExpense> Expenses { get { return _expenses; } }
}
我同意@Stefan的观点,暴露列表会破坏封装,通常应该避免。