jay*_*jay 5 c# design-patterns immutability
假设场景不允许实现不可变类型.根据这个假设,我想了解如何正确设计一个在消费后变成不可变的类型的意见/例子.
public class ObjectAConfig {
private int _valueB;
private string _valueA;
internal bool Consumed { get; set; }
public int ValueB {
get { return _valueB; }
set
{
if (Consumed) throw new InvalidOperationException();
_valueB = value;
}
}
public string ValueA {
get { return _valueA; }
set
{
if (Consumed) throw new InvalidOperationException();
_valueA = value;
}
}
}
Run Code Online (Sandbox Code Playgroud)
当ObjectA消耗ObjectAConfig:
public ObjectA {
public ObjectA(ObjectAConfig config) {
_config = config;
_config.Consumed = true;
}
}
Run Code Online (Sandbox Code Playgroud)
我不满意这简单有效,我想知道是否有更好的模式(排除,如所说,ObjectAConfig从开始设计变得不可变).
例如:
有意义定义一个monad Once<T>,允许包装的值只被初始化一次?
有意义定义一个返回类型本身改变私有字段的类型?
Mar*_*ell 10
您实施的有时会以" 冰棒不变性 " 为名称- 即您可以将其冻结.你当前的方法是有效的 - 事实上我在很多地方都使用过这种模式.
您可以通过以下方式减少一些重复:
private void SetField<T>(ref T field, T value) {
if (Consumed) throw new InvalidOperationException();
field = value;
}
public int ValueB {
get { return _valueB; }
set { SetField(ref _valueB, value); }
}
public string ValueA {
get { return _valueA; }
set { SetField(ref _valueA, value); }
}
Run Code Online (Sandbox Code Playgroud)
但是,还有另一种相关的方法:建设者.例如,拿走现有的课程:
public interface IConfig
{
string ValueA { get; }
int ValueB { get; }
}
public class ObjectAConfig : IConfig
{
private class ImmutableConfig : IConfig {
private readonly string valueA;
private readonly int valueB;
public ImmutableConfig(string valueA, int valueB)
{
this.valueA = valueA;
this.valueB = valueB;
}
}
public IConfig Build()
{
return new ImmutableConfig(ValueA, ValueB);
}
... snip: implementation of ObjectAConfig
}
Run Code Online (Sandbox Code Playgroud)
这里有一个真正不可变的实现IConfig,以及您原来的实现.如果您想要冻结版本,请致电Build().