设计一个可变类,在使用后它变得不可变

2024-02-08

假设该场景不允许实现不可变类型。根据这个假设,我想要关于如何正确设计一种类型的意见/示例,该类型在使用后变得不可变。

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

When ObjectA消耗ObjectAConfig:

public ObjectA {

  public ObjectA(ObjectAConfig config) {

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

我不满意这只是有效的,我想知道是否有更好的模式(排除,如上所述,使ObjectAConfig从一开始就设计为不可变)。

例如:

  • 定义一个 monad 是有意义的Once<T>允许包装值仅初始化一次?

  • 定义一个返回类型本身更改私有字段的类型是否有意义?


您正在实施的内容有时会以“冰棒不变性 http://blogs.msdn.com/b/ericlippert/archive/2007/11/13/immutability-in-c-part-one-kinds-of-immutability.aspx“ - 即你可以冻结它。你目前的方法将工作- 事实上,我自己在很多地方都使用了这种模式。

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

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

不过,还有另一种相关方法:构建器。例如,参加您现有的课程:

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().

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

设计一个可变类,在使用后它变得不可变 的相关文章

随机推荐

  • 解析c#类文件以获取属性和方法[重复]

    这个问题在这里已经有答案了 可能的重复 C 解析器 https stackoverflow com questions 81406 parser for c sharp 假设我有一个简单的类 例如 winforms 应用程序中的文本框控件内
  • 如何比较 viewDidLoad 和 viewDidAppear? [复制]

    这个问题在这里已经有答案了 我如何比较viewDidLoad and viewDidAppear 最好的办法是在视图控制器中实现这两种方法 该控制器加载带有子视图的视图 最简单的是来自 NIB 并在每个方法中放置一个断点 当应用程序在每个断
  • SQL Server 视图 - 错误的命名约定?

    DECLARE TableName AS VARCHAR 250 DECLARE SQL AS VARCHAR 500 DECLARE ViewCheck as CURSOR SET ViewCheck CURSOR FOR SELECT
  • 有没有办法从应用程序的 .ipa 存档中查看应用程序的 .entitlements 文件?

    我认为创建 ipa 时我的应用程序的 entitlements 文件存在问题 因此我想检查权利文件的捆绑 ID 在构建之前 我使用一个相当复杂的构建脚本来更改其中的一些内容 所以我想看看最终的产品是什么 我知道曾经有一个 Entitleme
  • 何时实施和扩展? [关闭]

    Closed 这个问题是基于意见的 help closed questions 目前不接受答案 什么时候应该implement or extend使用 有哪些现实世界的例子 它是否正确 实施似乎是强制类中存在某些方法并且这些方法函数调用格式
  • 检查委托是否为空

    我正在阅读 Essential C 3 0 一书 想知道这是否是检查委托是否为 null 的好方法 class Thermostat public delegate void TemperatureChangeHandler float n
  • cbind() 正在更改日期格式

    我正在尝试创建数据框的子集 当我这样做时 R 会切换日期列的格式 知道为什么或如何解决这个问题吗 gt head spyPr2 Date Open High Low Close Volume Adj Close 1 12 30 2011 1
  • Julia 中的方法链接

    I read https github com JuliaLang julia issues 5571 https github com JuliaLang julia issues 5571这让我觉得我可以因为一些评论而打破这样的界限 a
  • 无法在 systemd 203/EXEC 中将 Gunicorn 作为服务运行

    我正在尝试使用 Gunicorn WSGI Nginx 部署 FlaskApp 我已经尝试让它工作一段时间了 除了我一直遵循的数字海洋指南之外找不到任何东西 下面是我目前状态下的文件 我尝试了几种不同的调整mywebapp service文
  • 如何在 Chromium 浏览器中创建文本或将文本转换为音频?

    在尝试确定解决方案时如何在 chromium 上使用 Web Speech API https stackoverflow com questions 44013933 how to use web speech api at chromi
  • 对从方法调用的方法进行单元测试

    我有一个角度应用程序和一个在单击时触发的方法 在这个方法中 我将一个值传递给另一个私有方法 ts file public onViewItem item Results void const ids item data id this an
  • SQlite实体框架ADO.net提供程序错误1.0.92.0

    我试图了解 SQlite 和实体框架如何交互 我在 Visual Studio 2013 中创建了一个新的控制台项目 我安装了 SQlite 1 0 92 的 nuget 包 我创建一个新的空模型 edmx 并尝试从静态示例数据库 例如 N
  • opengl物体移动一段距离后振动

    我有一个在地形上移动的物体 第三人称摄像机跟随它 当我将它向不同方向移动一段距离后 即使它没有移动并且摄像机围绕它旋转 它也开始摇晃或振动 这就是移动对象的代码 double delta engine getDeltaTime GLfloa
  • Eclipse 无法启动 (Ubuntu):JVM 终止。退出代码=2

    我安装 ubuntu 14 04 LTS 64位 之后安装 Eclipse Luno Standard for 64bit 安装 Jdk 并使用以下链接按照设置 jdk 的所有步骤进行操作 http www wikihow com Inst
  • 使用 MOXy 和 XPath,是否可以解组两个属性列表?

    请注意 这不是我问的另一个问题的重复 使用 MOXy 和 XPath 是否可以解组属性列表 https stackoverflow com questions 6907225 with moxy and xpath is it possib
  • tf.keras.losses 中“BinaryCrossentropy”和“binary_crossentropy”的区别?

    我正在使用 tf GradientTape 使用 TensorFlow 2 0 训练模型 但我发现该模型的准确性为95 如果我使用tf keras losses BinaryCrossentropy 但降级为75 如果我使用tf keras
  • cURL 错误 60:SSL 证书:无法获取本地颁发者证书

    我尝试使用 Stripe 发送 API 请求 但收到错误消息 cURL 错误 60 SSL 证书问题 无法获取本地颁发者证书 这是我正在运行的代码 public function chargeStripe stripe new Stripe
  • 使用 ExecuteNonQueryAsync 并报告进度

    我以为我正在尝试做一些非常简单的事情 我只想在屏幕上报告一个运行数字 以便用户知道我正在执行的 SQL 存储过程正在工作 并且他们不会不耐烦并开始单击按钮 问题是我无法弄清楚如何实际调用 ExecutNonQueryAsync 命令的进度报
  • Python函数正在改变我输入的值,我不明白为什么

    这是我的第一个问题 所以如果我是一个完全愚蠢的人发布这个 请告诉我为什么以及我将来如何避免它 我有一些 python 代码 应该只需要一个列表 并将第 j 个分量乘以 1 这是有问题的代码 def flip spins j z spins
  • 设计一个可变类,在使用后它变得不可变

    假设该场景不允许实现不可变类型 根据这个假设 我想要关于如何正确设计一种类型的意见 示例 该类型在使用后变得不可变 public class ObjectAConfig private int valueB private string v