如何在C#中声明不可变的变量(值)? [英] How do I declare an immutable variable (value) in C#?

查看:497
本文介绍了如何在C#中声明不可变的变量(值)?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在Scala中,我可以写(这和C#中的意思完全一样)

In Scala I can write (and it will mean exactly the same thing it means in C#)

var v = 1;
v = 2;

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

but can't write (well, of course I can write but can't compile actually though the syntax is correct)

val v = 1;
v = 2;

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

Semicolons are not necessary but can be voluntarily used in Scala so I've decided to include them to let the code correspond C# more closely. val means an immutable value, a kind of a variable that can be only assigned once but, unlikely to c# consts can be initialized with a result of a run-time expression, unlikely to C# readonly fields can be introduced at any place in the code where a var variable can and, unlikely to C# immutable types is immune to a reference replacement, not just modification of the referenced object.

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

I enjoy the way C# introduces more and more functional coding candies in every new version of the language but miss this (arguably the most simple and the most essential) one heavily. In the majority of the cases I only assign values to my variables once so re-assignment is usually something that is not meant to happen which means a thing that is not expected and can cause a bug this way. Might I, perhaps, just be unaware of such a feature? I don't mind such a declaration looking a little bit clumsy (some F# imports perhaps, whatever they might look like in C# code).

更新:到目前为止似乎确实没有这样的功能(2017年3月,C#语言版本7.0),并且正如其他人所建议的,我已经提交了

UPDATE: As it seems there indeed is no such a feature a by now (March 2017, C# language version 7.0) and as suggested by others I have submitted an issue at the C# language design GitHub repository.

推荐答案

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

Basically, you can't - at least at the time of C#6 - with one notable exception mentioned below. Maybe something will change in future versions of C#. There were plans for "record types" for C# 7, it could open some way when paired with anonymous inline objects. However, I actually don't know what gets exactly added in C#7.

此类成员的唯一正常支持是在类成员范围内:

The only normal support for anything like that is at class member scope:

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则或多或少是显而易见的.

with read-only field being settable only during object member initialization or in constructor, and getters - well, should be more or less obvious.

在普通代码范围内,您创建的任何"变量"(与上述成员"或您提到的常量"相对)总是(几乎) >可写,并且赋值语义会始终有所不同,具体取决于变量类型的类型(结构/类).

At the scope of normal code, any 'variable' (as opposed to 'member' above, or 'constants' you mentioned) you create is (almost) always writable, and assignment semantics will always differ depending on the kind (struct/class) of the variable's type.

我找到了一个!您有关笨拙的语法的注释使我有了一个主意.实际上, foreach迭代器变量可以防止编译器进行分配,因此您可以将其与Enumerable.Repeat一起使用,以快速打开仅迭代一次的foreach范围.

I've found one! Your note about clumsy syntax got me an idea. Actually, the foreach iterator variable is guarded against assignments by the compiler, so you can use it with Enumerable.Repeat to quickly open a foreach scope that will iterate just once..

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

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

another option, nicer, 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"额外标识符(以及创建和处置元组对象的一些成本)

fields/properties of a Tuple are not writable, hence such tuple-literal will be quite handy, except for the 'pair2' extra identifier to write (and .. some cost of creating and disposing a tuple object)

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

However, I actually don't know if they are mutable or not. They are called "tuples", so I immediately think of "Tuple<>" whose properties are readonly, but then, in this old article

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

Tuples are value types, and their elements are simply public, mutable fields.

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

Now, I don't (yet) have VS2017 installed.. It will take some time, maybe someone else will be able to check that sooner than me.

这篇关于如何在C#中声明不可变的变量(值)?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆