如何在C#中声明不可变变量(值)?

Iva*_*van 3 .net c# syntax immutability

在Scala中我可以写(并且它意味着它在C#中意味着完全相同)

var v = 1;
v = 2;
Run Code Online (Sandbox Code Playgroud)

但是不能写(好吧,我当然可以编写,但实际上虽然语法正确但无法编译)

val v = 1;
v = 2;
Run Code Online (Sandbox Code Playgroud)

分号不是必需的,但可以在Scala中自愿使用,所以我决定将它们包含在内,让代码更紧密地对应C#.val表示一个不可变值,一种只能分配一次的变量,但不太可能const用运行时表达式的结果初始化c#,不太可能readonly在代码中的任何地方引入C#字段var变量可以和不太可能的C#不可变类型不受参考替换的影响,而不仅仅是对引用对象的修改.

我喜欢C#在每种新版本语言中引入越来越多功能性编码糖果的方式,但却错过了这一点(可以说是最简单也是最重要的).在大多数情况下,我只将值赋给我的变量一次,因此重新赋值通常是不会发生的事情,这意味着一个不期望的事情并且可能以这种方式导致错误.也许,我可能只是不知道这样的功能?我不介意这样的声明看起来有点笨拙(也许有些F#导入,无论它们在C#代码中看起来如何).

更新:由于现在看来确实没有这样的功能(2017年3月,C#语言版本7.0),并且正如其他人所建议的那样,我在C#语言设计GitHub存储库中提交了一个问题.

que*_*atl 5

基本上,你不能 - 至少在C#6时 - 有一个值得注意的例外,如下所述.也许在未来的C#版本中会有一些变化.C#7有"记录类型"的计划,它可以在与匿名内联对象配对时以某种方式打开.但是,我实际上不知道在C#7中添加了什么.

对类似事物的唯一正常支持是在类成员范围:

class Foo
{
    public readonly int shoeSize; // readonly field
    public int ShoeSize { get { .. } } // readonly property
    public int ToeSize { get; } = 5; // readonly property with initializer
    // ..etc
}
Run Code Online (Sandbox Code Playgroud)

只读字段只能在对象成员初始化或构造函数中设置,而getter - 好吧,应该或多或少显而易见.

在普通代码的范围内,您创建的任何" 变量 "(与上面的"成员"或"常量"相对)都是(几乎)总是可写的,并且赋值语义将始终根据类型(结构/类)而不同)变量的类型.

编辑:我找到了一个!你关于笨拙语法的注释让我有了一个想法.实际上,foreach迭代器变量被编译器防止分配,因此您可以将它与Enumerable.Repeat一起使用,以快速打开只迭代一次的foreach范围.

static void Main()
{
    foreach(int x in Enumerable.Repeat(5/*value for X*/, 1/*single run*/))
    {
        x=4;   // <- compile time error!
        Console.WriteLine(x);
    }
}
Run Code Online (Sandbox Code Playgroud)

EDIT2:另一个选项,更好的,元组文字,据说是在C#7中添加的

public static void Main()
{
        var pair1 = (42, "hello");
        System.Console.Write(Method(pair1).message);

        var pair2 = (code: 43, message: "world");
        System.Console.Write(pair2.message);
}
Run Code Online (Sandbox Code Playgroud)

元组的字段/属性是不可写的,因此这样的元组文字将非常方便,除了要写的'pair2'额外标识符(以及创建和处理元组对象的一些成本)

但是,我实际上不知道它们是否可变.它们被称为"元组",因此我立即想到"Tuple <>",其属性是只读的,但是,在这篇旧文章中

元组是值类型,它们的元素只是公共的,可变的字段.

现在,我还没有安装VS2017 ..这需要一些时间,也许其他人可以比我更快地检查.

  • @Ivan Go请求官方回购!https://github.com/dotnet/csharplang (2认同)