在Scala中,我可以写(这意味着它在C#中意味着完全相同)
var v = 1;
v = 2;
但是不能写(好吧,当然我可以编写,但实际上虽然语法正确但无法编译)
val v = 1;
v = 2;
分号不是必需的,但可以在Scala中自愿使用,所以我决定将它们包含在内,让代码更紧密地与C#相对应。 val
表示一个不可变值,一种只能分配一次的变量,但不太可能c#const
s可以用运行时表达式的结果初始化,不太可能是C#{{ 1}}字段可以在代码中的任何位置引入,其中readonly
变量可以并且不太可能使C#不可变类型对引用替换不敏感,而不仅仅是对引用对象的修改。
我喜欢C#在每种新版语言中引入越来越多功能性编码糖果的方式,但却错过了这一点(可以说是最简单也是最重要的)。在大多数情况下,我只将值赋给我的变量一次,因此重新赋值通常是不会发生的事情,这意味着一个不期望的事情并且可能以这种方式导致错误。也许,我可能只是不知道这样的功能?我不介意这样的声明看起来有点笨拙(可能是一些F#导入,无论它们在C#代码中看起来像什么)。
更新:由于现在看来确实没有这样的功能(2017年3月,C#语言版本7.0),并且正如其他人所建议的那样,我提交了issue at the C# language design GitHub repository。< / p>
答案 0 :(得分: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
}
只读字段只能在对象成员初始化期间或构造函数中设置,而getter - 好吧,应该或多或少显而易见。
在普通代码的范围内,您创建的任何“变量”(与上面的“成员”或“您提到的”常量“相对)(几乎)总是 writable,赋值语义总是根据变量类型的种类(结构/类)而不同。
编辑:我找到了一个!你关于笨拙语法的注释让我有了一个想法。实际上, 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'额外标识符(以及创建和处理元组对象的一些成本)
但是,我实际上不知道是否可变。它们被称为“元组”,因此我立即想到“元组&lt;&gt;”其属性是只读的,但是in this old article
元组是值类型,它们的元素只是公共的可变字段。
现在,我还没有安装VS2017 ..这需要一些时间,也许别人可以比我早点检查。