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'方法吗?理想情况下,我想利用内置的列表功能,而不是重新发明轮子。

IEnumerable与List在具体类实现中的对比

这取决于您实际想要做什么。不建议使用ListIList属性,因为您可以使用它做任何事情(如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, RemoveClear等方法。但是,如果主要用例是一次性设置所有项,则只能使用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的观点,暴露列表会破坏封装,通常应该避免。