【问题标题】:How do I declare an immutable variable (value) in C#? [duplicate]如何在 C# 中声明不可变变量(值)? [复制]
【发布时间】:2017-03-21 00:14:35
【问题描述】:

我可以在 Scala 中编写(这与在 C# 中的含义完全相同)

var v = 1;
v = 2;

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

val v = 1;
v = 2;

分号不是必需的,但可以在 Scala 中自愿使用,因此我决定包含它们以使代码更紧密地对应 C#。 val 表示一个不可变的值,一种只能赋值一次的变量,但不太可能 c# consts 可以用运行时表达式的结果初始化,不太可能 C# readonly 字段可以在代码中的任何位置引入 var 变量,并且不太可能 C# 不可变类型不受引用替换的影响,而不仅仅是对引用对象的修改。

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

更新:目前看来确实没有这样的功能(2017 年 3 月,C# 语言版本 7.0),并且按照其他人的建议,我已经提交了 issue at the C# language design GitHub repository

【问题讨论】:

    标签: c# .net syntax immutability


    【解决方案1】:

    基本上,你不能——至少在 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
    }
    

    只读字段只能在对象成员初始化期间或在构造函数和 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);
        }
    }
    

    EDIT2:另一个选项,更好,tuple literal that is said to be added in 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);
    }
    

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

    但是,我实际上不知道它们是否可变。它们被称为“元组”,所以我立即想到了“元组”,它的属性是只读的,但是,in this old article

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

    现在,我(还)没有安装 VS2017。这需要一些时间,也许其他人会比我更早检查。

    【讨论】:

    • 第 7 版已经出来了,VS2017 用的就是这个。
    • @DavidG:谢谢!我以为它还在测试阶段,现在好像已经出来了,我会检查发行说明并更新答案
    • @quetzalcoatl 不错的技巧(foreach)!不过对于现实生活来说太笨拙了。但我已经怀疑是否存在合理的东西。
    • @Ivan Go 在官方 repo 上请求它! github.com/dotnet/csharplang
    • @Ivan 这可能是最好的提问地点,会议记录也可以在那里阅读,它可能是相当有趣的东西。你可能也想看看这个github.com/dotnet/roslyn
    猜你喜欢
    • 2013-04-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-03-20
    • 2013-01-15
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多