【问题标题】:C# calculating an immutable variableC# 计算不可变变量
【发布时间】:2015-03-11 10:47:10
【问题描述】:

有没有办法告诉编译器,从这里开始,表达式的结果应该被认为是不可变的?

...
"const" MyClass str = b[0].x+b[1].x;
... // from here on str is an immutable object

还有 const 或 readonly 变量对性能有好处吗?


添加:@Onur: (a) 应允许分配新值; (b) 不允许使用 str 的当前值,包括可以通过 str 访问的所有内容,例如 str 的任何字段以及 str 以任何方式引用的所有内容; (c) 举例可能很困难。但我试图改写它。 str 应该是任何类型的数据结构(对象、集合和它们的任何混合)。将分配给 str 的对象是可变的,并且可以被另一个引用修改。但是当分配给 str 时,我想确保通过 str 不能修改对象。其背后的想法是,对象一旦创建,将被传递给不同的线程以处理对象的数据,我想确保我不会意外修改通过引用传递给不同线程的对象.所以我想要某种参考来防止我修改任何数据。假设我想要某种使完整对象只读的引用。

【问题讨论】:

  • 看起来您混淆了 constness 和 immutability。字符串在 C# 中已经是不可变的。
  • const 或 readonly 没有显着的性能优势,它们主要是为了提高可维护性。
  • 我认为 const 变量不应该在运行时改变(初始化)。
  • 我将 String 更改为 MyClass。没想到 String 默认是只读的。
  • 您能否澄清一下 (a) str 是否不应该被分配一个新值; (b) str 的当前值不可修改或 (c) 有所不同;也许一个例子可以帮助展示什么应该(不)被允许

标签: c# immutability


【解决方案1】:

您不能有readonly 局部变量(例如参见Why does C# disallow readonly local variables?)。您可以在类/结构中有一个只读字段。我认为它们的访问速度并不比普通的局部变量/普通的字段变量快。

请注意,每个 Jon Skeet 只读字段 速度较慢 :-)

你可以有一个const 局部变量,但它只能有可以在编译时计算的值。 const 变量/字段比变量更快,因为它已被编译器删除:-)(至少它对 JIT 更快,因为它甚至不存在于 IL 代码中)

这个:

const int xxx = 1;
const int yyy = xxx + 1;
Console.WriteLine(yyy);

编译成

Console.WriteLine(2);

(使用 ILSpy 进行检查,即使在调试模式下)

【讨论】:

    【解决方案2】:
    1. 您不能为 const 分配除另一个常量之外的任何值。 但是,您可以定义一个私有变量,该变量可以在其类中使用您想要的任何值进行初始化,并简单地使用其值公开一个只读属性。

    2. 常量与不可变不同。常量的值不能更改,而指向不可变对象(如字符串)的引用的值可以更改。 当您有一个字符串变量并更改它的值时,.Net 层下发生的事情是该字符串被破坏并且新的字符串值替换它。这就是不可变的意思。

    【讨论】:

      【解决方案3】:

      你可能混淆了三个不同的概念:

      • 不可变指的是对象:不可变对象是不能改变状态的对象,你只能在之前的对象的基础上创建一个新的对象。

      • const 指的是常量。常量是一个变量,其中 value 在编译时是/可以知道的。例如(有小错误):

        public const double Pi = 3.14159265358979;
        public const double PiHalf = Pi/2;
        

        编译器可以简单地推断常量,以及 - 可选地 - 内联时间。 对象通常没有常量,因为它们需要在堆上分配,可以有多个对它们的引用,等等。

      • Readonly: readonly 意味着您向字段写入一次(在构造函数级别),然后再也不会更改它们的值。

      C# 允许将(局部)变量标记为常量,但如前所述,这意味着必须在编译时知道该值。所以你不能——比如说——从标准输入中读取一个值,然后说变量将保持不变。然而,由于b 很可能是一个对象数组,因此参数不是常量,因此结果也不是。因此,您的陈述将失败。

      然而,活性分析是大多数编译器执行的一个过程,在许多情况下可以检测到变量不会被修改。

      【讨论】:

        猜你喜欢
        • 2013-07-06
        • 2019-04-19
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-02-24
        相关资源
        最近更新 更多