简体   繁体   English

在几个构造函数中重复的只读属性设置代码

[英]Readonly property set code repeated in several constructor

I have a DataStructure class, which I want to be immutable. 我有一个DataStructure类,我希望它是不可变的。

Ordinarily, I'd just ensure that all my members are defined as readonly - Job Done. 通常,我只是确保将我的所有成员都定义为readonly -作业完成。 But one of the members is a list (of ints), so I need to ensure that the List can't be modified; 但是成员之一是一个列表(整数),因此我需要确保该List不能被修改; so I change it to a ReadOnlyCollection<T> . 所以我将其更改为ReadOnlyCollection<T> Fine. 精细。

I also need that collection to be ordered in a certain way - again fine, I sort the list accordingly before converting it via .AsReadOnly() . 我还需要以某种方式对集合进行排序-再次好,在通过.AsReadOnly()对其进行转换之前,我对列表进行了相应的排序。

So far, it's all been fine. 到目前为止,一切都很好。

But the last step is that I want 3 different constructors - each accepting the original data in a different format. 但是最后一步是我需要3个不同的构造函数-每个构造函数都接受不同格式的原始数据。 Now I have to duplicate the code that converts the list to the necessary format, in each constructor. 现在,我必须在每个构造函数中复制将列表转换为必要格式的代码。

If I commonise it out into a setList() method, then the variable can't be readonly , because it's being assigned in a non-constructor method. 如果我将其setList()化为setList()方法,则该变量不能为readonly ,因为它是在非构造方法中分配的。 Now I've lost some of the immutability. 现在我已经失去了一些不变性。

Ideally, there would be some way that I can declare that the setList method can only be called from a constructor, and thus is allowed to edit readonly members, but I don't think that exists. 理想情况下,我可以通过某种方式声明只能从构造函数中调用setList方法,从而可以编辑readonly成员,但我认为这不存在。

I could create wrap everything in getters and so forth, so that the class is immutable from the outside, but I'd rather like it to be immutable from the inside too (especially given that I can achieve this is I sacrifice DRYness) 我可以将所有内容包装在吸气剂中,依此类推,这样该类从外部是不可变的,但是我希望它也从内部是不可变的(特别是考虑到我可以实现这一点,就是我牺牲了DRYness)

Does anyone have any clever ideas about language features I've forgotten about that would solve this? 是否有人对我已经遗忘的语言功能有任何聪明的想法可以解决此问题?

Rather than using a void SetList(List) called from constructors, you could have a List PrepareList(List) . 您可以使用List PrepareList(List)而不是使用从构造函数调用的void SetList(List) List PrepareList(List) This method would prepare the list, and return it to the callers -ie: the constructors. 此方法将准备列表,并将其返回给调用者-即:构造函数。

So the code wouldn't be repeated -except an affectation _list = PrepareList(list) in each constructors. 因此,该代码将不会重复-除了每个构造函数中的_list = PrepareList(list)

You can keep it as a normal list inside your class, but only expose it as readonly to the outside (just return .AsReadOnly() in a property). 您可以将其作为类中的普通列表保留,但仅将其作为只读暴露给外部(只需在属性中返回.AsReadOnly() )。

Though if you definetely want the internal immutability, constructors can call each other: 尽管如果您确实希望内部不变性,则构造函数可以相互调用:

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

So you can have most of the code in one constructor (even a private one if needed), and have the converting done in the others. 因此,您可以将大多数代码包含在一个构造函数中(如果需要,甚至可以包含一个私有的构造函数),并在其他构造函数中进行转换。 Edit: it is a bit difficult to do alot of work that way, so I still think you should move the conversion out into methods. 编辑:用这种方法很难完成很多工作,因此我仍然认为您应该将转换移到方法中。 If the method doesn't access any class members, it'd still be internally immutable. 如果该方法不访问任何类成员,则它在内部仍然是不可变的。

Another pattern I personally prefer (even if it's just syntactically different) is: 我个人更喜欢的另一种模式(即使只是在语法上有所不同)是:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM