如何与 readonly class 成员共享构造函数代码?
How can I share constructor code with readonly class members?
我有一个 class、FooBarSet
和一个 "core" 初始化逻辑块。
一个FooBar
是由一个Foo
和一个Bar
组成的。 Class 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
,如何让这些构造函数共享初始化代码?
您可以将 "zipper" 代码移动到静态函数并使用它:
public class FooBarSet
{
private readonly List<FooBar> _list;
private static List<FooBar> Prepare( List<Foo> fooList, List<Bar> barList )
{
return fooList.Zip(barList, (foo, bar) => new FooBar(foo, bar));
}
public FooBarSet(List<Foo> fooList, List<Bar> barList) :
this( Prepare( fooList, barList ) )
{
}
public FooBarSet(List<FooBar> zippedList)
{
_list = zippedList;
}
}
简单的答案就是获取Init
方法return在构造函数中设置的值:
public class FooBarSet
{
private readonly List<FooBar> _list;
// Common "constructor" called from actual constructors.
private List<FooBar> Init(List<FooBar> foobarList)
{
// Contracts and initialization...
return whateverList;
}
public FooBarSet(List<FooBar> foobarList)
{
_list = Init(foobarList);
}
public FooBarSet(List<Foo> fooList, List<Bar> barList)
{
var zipped = fooList.Zip(barList,
(foo, bar) => new FooBar(foo, bar));
_list = Init(zipped);
}
}
我有一个 class、FooBarSet
和一个 "core" 初始化逻辑块。
一个FooBar
是由一个Foo
和一个Bar
组成的。 Class 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
,如何让这些构造函数共享初始化代码?
您可以将 "zipper" 代码移动到静态函数并使用它:
public class FooBarSet
{
private readonly List<FooBar> _list;
private static List<FooBar> Prepare( List<Foo> fooList, List<Bar> barList )
{
return fooList.Zip(barList, (foo, bar) => new FooBar(foo, bar));
}
public FooBarSet(List<Foo> fooList, List<Bar> barList) :
this( Prepare( fooList, barList ) )
{
}
public FooBarSet(List<FooBar> zippedList)
{
_list = zippedList;
}
}
简单的答案就是获取Init
方法return在构造函数中设置的值:
public class FooBarSet
{
private readonly List<FooBar> _list;
// Common "constructor" called from actual constructors.
private List<FooBar> Init(List<FooBar> foobarList)
{
// Contracts and initialization...
return whateverList;
}
public FooBarSet(List<FooBar> foobarList)
{
_list = Init(foobarList);
}
public FooBarSet(List<Foo> fooList, List<Bar> barList)
{
var zipped = fooList.Zip(barList,
(foo, bar) => new FooBar(foo, bar));
_list = Init(zipped);
}
}