我正在为财务建模编写一个类库。
我想使用接口来定义模型,以便为测试创建抽象,以及稍后可能添加新的具体类。
我正在努力研究如何定义事物列表,所以我稍后可以在具体类中添加这些列表。
例如,如果我将一个接口定义为在我的模型中有一个名为
的费用列表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功能,而不是重新发明轮子。
答案 0 :(得分:1)
这取决于你真正想做的事情。建议不要使用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相同。您可以考虑在内部将其保留为数组。
答案 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,暴露一个列表打破封装,一般应该避免。