假设该场景不允许实现不可变类型。按照这个假设,我想就如何正确设计一种在使用后变得不可变的类型提供意见/示例。

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

ObjectA使用ObjectAConfig时:
public ObjectA {

  public ObjectA(ObjectAConfig config) {

    _config = config;
    _config.Consumed = true;
  }
}

我不满意这是否行得通,我想知道是否有更好的模式(如所排除的那样,从设计开始就使ObjectAConfig不可变)。

例如:
  • 可以像Once<T>这样定义一个monad,使包装的值仅初始化一次吗?
  • 可以有意义地定义一个类型,该类型返回更改了私有(private)字段的类型本身吗?
  • 最佳答案

    有时您要实现的名称称为“popsicle immutability”-即您可以将其卡住。您当前的方法会奏效-实际上,我在很多地方都使用了这种模式。

    您可以通过以下方式减少重复:

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

    但是,还有另一种相关方法:构建器。例如,参加您现有的类(class):
    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
    }
    

    这里是IConfig的真正不变的实现,以及您的原始实现。如果需要卡住版本,请调用Build()

    关于c# - 设计一个可变的类,使其在被消耗后变得不可变,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/15088773/

    10-09 15:02
    查看更多