Inc*_*ito 98 c# language-agnostic language-design
对于C++开发人员来说,它看起来很奇怪 在C++中,我们用来标记参数,const
以确保它的状态不会在方法中改变.还有其他C++特定的原因,比如const ref
为了传递ref而传递,并确保状态不会被更改.但是为什么我们不能在C#中标记为方法参数const?
为什么我不能像下面那样声明我的方法?
....
static void TestMethod1(const MyClass val)
{}
....
static void TestMethod2(const int val)
{}
....
Run Code Online (Sandbox Code Playgroud)
Eri*_*ert 58
除了其他好的答案之外,我还要补充另一个原因,就是不要将C风格的常量放入C#中.你说:
我们将参数标记为const,以确保其状态不会在方法中更改.
如果const实际上这样做,那将是伟大的.Const不这样做.常数是谎言!
Const不保证我可以实际使用.假设您有一个采用const事物的方法.有两个代码作者:编写调用者的人和编写被调用者的人.被调用者的作者使该方法采用了const.这两位作者可以假设对象是不变的吗?
没有.被调用者可以自由地抛弃const并改变对象,因此调用者无法保证调用带有const的方法实际上不会改变它.类似地,被调用者不能假设对象的内容在被调用者的整个动作中都不会改变; 被调用者可以在const对象的非常量别名上调用一些变异方法,现在所谓的const对象已经改变了.
C风格的const不保证对象不会改变,因此被破坏.现在,C已经有了一个弱类型系统,你可以在这个系统中重新解释一个double转换为一个int,如果你真的想要的话,那么它对于const也有一个弱类型系统也就不足为奇了.但是C#被设计成一个好的类型系统,一个类型系统,当你说"这个变量包含一个字符串"时,变量实际上包含对字符串的引用(或null).我们绝对不希望将C风格的"const"修饰符放入类型系统中,因为我们不希望类型系统成为谎言.我们希望类型系统很强大,以便您可以正确地推理您的代码.
C中的Const是一个指导原则 ; 它基本上意味着"你可以相信我不要试图改变这件事".那不应该是类型系统 ; 类型系统中的东西应该是关于你可以推理的对象的事实,而不是它的使用指南.
现在,不要误会我的意思; 仅仅因为C中的const被深深打破并不意味着整个概念是无用的.我希望看到的是C#中一些实际上正确且有用的"const"注释形式,这是人类和编译器可以用来帮助他们理解代码的注释,运行时可以用来做自动并行化和其他高级优化.
例如,想象一下,如果你可以围绕一大堆代码"画一个盒子"并说"我保证这段代码不会对这个类的任何字段执行任何突变",这种方式可以由编译器检查.或者画一个框,上面写着"这个纯粹的方法会改变对象的内部状态,但不会以任何方式在框外观察".这样的对象不能自动安全地多线程,但可以自动记忆.我们可以在代码上添加各种有趣的注释,以实现丰富的优化和更深入的理解.我们可以比弱C风格的const注释做得更好.
但是,我强调这只是猜测.我们没有确定的计划将此类功能纳入任何假设的未来版本的C#,如果有的话,我们还没有宣布这种方式.这是我希望看到的东西,以及即将强调多核计算可能需要的东西,但这些都不应被解释为对C#的任何特定特征或未来方向的预测或保证.
现在,如果您想要的仅仅是局部变量的注释,这是一个参数,表示"此参数的值在整个方法中不会改变",那么,当然,这很容易完成.我们可以支持一次初始化的"readonly"本地和参数,以及在方法中改变的编译时错误."using"语句声明的变量已经是一个本地变量; 我们可以为所有本地和参数添加一个可选的注释,使它们像"使用"变量一样.它从未成为一个非常高优先级的功能,因此从未实现过.
Rub*_*ben 24
C#中没有const正确性的原因之一是因为它在运行时级别不存在.请记住,除非它是运行时的一部分,否则C#1.0没有任何功能.
CLR没有const正确概念的几个原因是例如:
Const正确性几乎是C++中仅存在的语言特性.因此,它几乎归结为同样的论证,即为什么CLR不需要检查异常(这是一种仅Java语言的特性).
另外,我认为您不能在托管环境中引入这种基本类型系统功能而不会破坏向后兼容性.因此,不要指望进入C#世界的const正确性.
Ste*_*ary 12
我相信C#不是const-correct有两个原因.
首先是可理解性.很少有C++程序员理解const正确性.简单的例子const int arg
是可爱的,但我也看到了char * const * const arg
- 一个常量指针指向非常量字符的常量指针.指向函数的指针的const-correctness是一个全新的混淆程度.
第二个是因为类参数是通过值传递的引用.这意味着已经有两个级别的常量要处理,没有明显清晰的语法.类似的绊脚石是集合(以及集合的集合等).
正确性是C++类型系统的重要组成部分.从理论上讲,它可以添加到C#中,只能在编译时检查(它不需要添加到CLR中,除非包含const成员方法的概念,否则不会影响BCL) .
但是,我认为这不太可能:第二个原因(语法)很难解决,这将使第一个原因(可理解性)成为一个问题.
从 C# 7.2(2017 年 12 月,Visual Studio 2017 15.5)开始,这是可能的。
仅适用于结构和基本类型!, 不适用于类的成员。
您必须使用in
来通过引用将参数作为输入发送。看:
请参阅:https : //docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/in-parameter-modifier
对于您的示例:
....
static void TestMethod1(in MyStruct val)
{
val = new MyStruct; // Error CS8331 Cannot assign to variable 'in MyStruct' because it is a readonly variable
val.member = 0; // Error CS8332 Cannot assign to a member of variable 'MyStruct' because it is a readonly variable
}
....
static void TestMethod2(in int val)
{
val = 0; // Error CS8331 Cannot assign to variable 'in int' because it is a readonly variable
}
....
Run Code Online (Sandbox Code Playgroud)
const
在C#中表示"编译时常量",而不是像C++中那样"只读"但可能是其他代码可变的".const
C#中C++的粗略模拟是readonly
,但是那个只适用于字段.除此之外,没有C++ - 就像C#中的const正确概念一样.
理由很难说清楚,因为有很多潜在的原因,但我的想法是希望首先保持语言的简单性,以及实现这一点的不确定优势.