如何与只读类成员共享构造函数代码

本文关键字:共享 构造函数 代码 成员 只读 | 更新日期: 2023-09-27 18:03:48

我有一个类,FooBarSet具有单个初始化逻辑的"核心"块。

一个FooBar由一个Foo和一个Bar组成。类FooBarSetFooBar的列表初始化。FooBarSet也可以通过单独的并行FooBar列表初始化

理想情况下,我可以这样运行它:

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)是非法的。常见的解决方案,就像这个答案一样,是将核心初始化拉到一个公共私有方法中:

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,我如何让这些构造函数共享初始化代码?

如何与只读类成员共享构造函数代码

简单的答案是让Init方法返回要在构造函数中设置的值:

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);
    }
}

您可以将"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;
    }
}