具体 class 实现中的 IEnumerable 与 List
IEnumerable versus List in a concrete class implementation
我正在编写一个 class 金融建模库。
我想使用接口定义模型以创建用于测试的抽象,并可能在以后添加新的具体 classes。
我正在为如何定义事物列表而苦苦挣扎,以便稍后可以在具体的列表中添加这些列表 class。
例如,如果我将一个接口定义为在我的模型中有一个费用列表,名为
IEnumerable 费用 {get;设置;}
然后想创建一个名为 ABCModel 的具体 class,其中包含一个具体的 XYZExpense 列表,实施列表的最佳方式是什么,以便我可以轻松地向列表中添加更多项目?
我无法将列表转换为 IEnumerable。
例如:
public interface IFinancialModel
{
IEnumerable<IExpense> Expenses { get; }
IEnumerable<IRevenue> Revenue { get; }
IEnumerable<IAsset> Assets { get; }
IEnumerable<ILiability> Liabilities { get; }
}
我需要一个名为 public class 的具体 class FinancialModel : IFinancialModel
并能够添加具体项目。
我应该创建自己的 'Add' 方法吗?理想情况下,我想利用内置的列表功能而不是重新发明轮子。
这取决于你真正想做什么。不推荐拥有 List
或 IList
属性,因为你可以用它做任何事情(如 Clear
、Add
等等)而无需拥有 class 知道关于它。这不利于封装。您将无法对更改执行某些操作(例如设置脏标志、触发已更改的事件或进行验证)。
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 的观点,公开列表会破坏封装,通常应避免这样做。
我正在编写一个 class 金融建模库。
我想使用接口定义模型以创建用于测试的抽象,并可能在以后添加新的具体 classes。
我正在为如何定义事物列表而苦苦挣扎,以便稍后可以在具体的列表中添加这些列表 class。
例如,如果我将一个接口定义为在我的模型中有一个费用列表,名为
IEnumerable 费用 {get;设置;}
然后想创建一个名为 ABCModel 的具体 class,其中包含一个具体的 XYZExpense 列表,实施列表的最佳方式是什么,以便我可以轻松地向列表中添加更多项目?
我无法将列表转换为 IEnumerable。
例如:
public interface IFinancialModel
{
IEnumerable<IExpense> Expenses { get; }
IEnumerable<IRevenue> Revenue { get; }
IEnumerable<IAsset> Assets { get; }
IEnumerable<ILiability> Liabilities { get; }
}
我需要一个名为 public class 的具体 class FinancialModel : IFinancialModel
并能够添加具体项目。
我应该创建自己的 'Add' 方法吗?理想情况下,我想利用内置的列表功能而不是重新发明轮子。
这取决于你真正想做什么。不推荐拥有 List
或 IList
属性,因为你可以用它做任何事情(如 Clear
、Add
等等)而无需拥有 class 知道关于它。这不利于封装。您将无法对更改执行某些操作(例如设置脏标志、触发已更改的事件或进行验证)。
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 的观点,公开列表会破坏封装,通常应避免这样做。