【问题标题】:Readonly property set code repeated in several constructor在几个构造函数中重复的只读属性集代码
【发布时间】:2014-07-06 14:18:41
【问题描述】:

我有一个 DataStructure 类,我希望它是不可变的。

通常,我会确保我的所有成员都被定义为readonly - Job Done。 但是其中一个成员是一个列表(整数),所以我需要确保List 不能被修改;所以我把它改成ReadOnlyCollection<T>。很好。

我还需要以某种方式对该集合进行排序 - 再次很好,我在通过 .AsReadOnly() 转换之前对列表进行了相应的排序。

到目前为止,一切都很好。

但最后一步是我想要 3 个不同的构造函数——每个构造函数都接受不同格式的原始数据。 现在我必须在每个构造函数中复制将列表转换为必要格式的代码。

如果我将其通用化为setList() 方法,则该变量不能是readonly,因为它是在非构造方法中分配的。现在我失去了一些不变性。

理想情况下,我可以通过某种方式声明 setList 方法只能从构造函数调用,因此允许编辑 readonly 成员,但我认为不存在。

我可以在 getter 等中创建包装所有内容,以便该类从外部是不可变的,但我更希望它从内部也是不可变的(特别是考虑到我可以实现这一点,我牺牲了 DRYness )

有人对我忘记的语言功能有什么聪明的想法可以解决这个问题吗?

【问题讨论】:

  • 将成员标记为只读不会使集合不可变...

标签: c# constructor immutability readonly readonly-collection


【解决方案1】:

您可以使用List PrepareList(List),而不是使用从构造函数调用的void SetList(List)。此方法将准备列表,并将其返回给调用者 - 即:构造函数。

所以代码不会重复 - 除了每个构造函数中的 _list = PrepareList(list) 做作。

【讨论】:

  • 啊,完美!正是我想要的。
【解决方案2】:

您可以将其作为普通列表保留在您的类中,但只能将其作为只读方式向外部公开(只需在属性中返回 .AsReadOnly())。

虽然如果你明确想要内部不变性,构造函数可以相互调用:

public Foo( int a ) { ... }
public Foo( string a ) : this( int.Parse( a ) ) { ... }

因此,您可以将大部分代码放在一个构造函数中(如果需要,甚至可以使用私有构造函数),并在其他构造函数中完成转换。编辑:以这种方式做很多工作有点困难,所以我仍然认为你应该将转换移到方法中。如果该方法不访问任何类成员,它仍然是内部不可变的。

我个人更喜欢的另一种模式(即使只是语法不同)是:

private Foo( int a ) { ... }

public static Foo FromBar( Bar b )
{
    int x;
    // convert from Bar here
    return new Foo( x );
}

public static Foo FromSomethingElse( SomeThingElse b )
{
    int x;
    // convert from SomeThingElse here
    return new Foo( x );
}

【讨论】:

  • 是的,我考虑过将构造函数链接在一起的选项,但是主体比简单的 int.Parse() 复杂得多,并且列表不是我从输入中提取的唯一成员.我想我可以定义一堆方法来提取 vrious 列表和其他东西,但总体上感觉有点难看。使用静态“构造函数”之类的方法,然后遵循真正的构造函数来设置只读成员是一个不错的设计。并且失败了我会使用的任何其他解决方案。
  • 那么我会说使用静态方法,它会给你更多的工作空间!
猜你喜欢
  • 1970-01-01
  • 2017-01-10
  • 2019-12-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-03-17
相关资源
最近更新 更多