在具体的类实现中IEnumerable与List

时间:2016-09-12 18:08:03

标签: c# .net oop interface concrete

我正在为财务建模编写一个类库。

我想使用接口来定义模型,以便为测试创建抽象,以及稍后可能添加新的具体类。

我正在努力研究如何定义事物列表,所以我稍后可以在具体类中添加这些列表。

例如,如果我将一个接口定义为在我的模型中有一个名为

的费用列表

IEnumerable Expenses {get; set;}

后来想要创建一个名为ABCModel的具体类,其中包含一个具体的XYZExpense列表,这是实现列表的最佳方法,这样我就可以轻松地将更多项添加到列表中?

我无法将List强制转换为IEnumerable。

例如:

 public interface IFinancialModel
{
    IEnumerable<IExpense> Expenses { get; }
    IEnumerable<IRevenue> Revenue { get; }
    IEnumerable<IAsset> Assets { get; }
    IEnumerable<ILiability> Liabilities { get; }
}

我需要一个名为public class FinancialModel的具体类:IFinancialModel

并能够添加具体项目。

我应该创建&#39;添加&#39;我自己的方法?理想情况下,我想利用内置的List功能,而不是重新发明轮子。

2 个答案:

答案 0 :(得分:1)

这取决于你真正想做的事情。建议不要使用ListIList属性,因为您可以使用它完成所有操作(例如ClearAdd等),而无需拥有类知道它。这对封装不利。您将无法在更改时执行某些操作(例如设置脏标志,触发更改事件或进行验证)。

IEnumerable是个不错的选择。

您可以添加setter,但不应该通过引用获取为该属性设置的值。它可以是任何内容,例如Linq查询甚至是数据库查询,您不想引用它们。你只想要这些物品。 (还要考虑对来自外部的集合的引用可以分配给其他实例,当它在那里更改时会导致非常糟糕的副作用,但不应在此处更改。)

// example implementation with a setter
private List<IExpense> expenses 

public IEnumerable<IExpense> Expenses 
{ 
  get { return expenses; }
  set { expenses = value.ToList(); }
}

或者,您可以实施自己的AddAddRangeRemoveClear等方法。但是,如果主要用例是一次性设置所有项目,则只能使用SetExpenses方法,这与我之前显示的属性上的setter相同。您可以考虑在内部将其保留为数组。

答案 1 :(得分:0)

您要找的是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,暴露一个列表打破封装,一般应该避免。