【发布时间】:2015-07-21 21:50:37
【问题描述】:
我有一个类,FooBarSet,它有一个“核心”初始化逻辑块。
FooBar 由Foo 和Bar 组成。类FooBarSet 使用FooBar 列表初始化。 FooBarSet 可以也通过单独的并行 Foo 和 Bar 列表进行初始化。
理想情况下,我可以这样运行它:
public class FooBarSet
{
private readonly List<FooBar> _list;
// Primary constructor.
public FooBarSet(List<FooBar> foobarList)
{
// Contracts and initialization...
_list = foobarList;
}
// Secondary constructor.
public FooBarSet(List<Foo> fooList, List<Bar> barList)
{
// Zip a new list of new FooBars
var zipped = fooList.Zip(barList,
(foo, bar) => new FooBar(foo, bar));
// Call primary constructor with zipped list.
this(zipped);
}
}
这是 C#,不是 Java,所以this(zipped) 是非法的。常见的解决方案as in this answer,就是把核心初始化拉到一个常用的私有方法中:
public class FooBarSet
{
private readonly List<FooBar> _list;
// Common "constructor" called from actual constructors.
private Init(List<FooBar> foobarList)
{
// Contracts and initialization...
_list = foobarList;
}
public FooBarSet(List<FooBar> foobarList)
{
Init(foobarList);
}
public FooBarSet(List<Foo> fooList, List<Bar> barList)
{
var zipped = fooList.Zip(barList,
(foo, bar) => new FooBar(foo, bar));
Init(zipped);
}
}
但是,这也不起作用,因为 readonly _list 字段。
假设_list必须是readonly,我怎样才能让这些构造函数共享初始化代码?
【问题讨论】:
-
_list = Init(foobarList)在构造函数中?让Init改为返回List<FooBar>。 -
@RonBeyer,我非常喜欢。它适用于我的实际实现,而不仅仅是我使用的MWE。把它作为答案扔掉,只要不出现疯狂美丽的东西,它就是你的。
-
附注:只有列表的reference是只读的,您可以随时更改contents。那么显而易见的解决方案......
-
@Clockwork-Muse,我假设您暗示删除
readonly修饰符。在这个MWE 中,这当然是这样做的方法:-) 但在我的实际用例中,该引用是对不可变引用类型的。 -
不,这个想法是您可以只更改内容,但仍保留引用
readonly。显然,如果实际类型是不可变的(这是不可能的),这将不起作用。
标签: c# constructor dry