为什么在C#中不允许const参数?

对C ++开发人员来说,这看起来很奇怪。 在C ++中,我们用一个参数标记为const ,以确保它的状态不会在方法中改变。 还有其他C ++特定的原因,比如传递const ref以便通过ref传递,并确保状态不会被改变。 但为什么我们不能在C#中标记为方法参数const?

为什么我不能像以下声明我的方法?

  .... static void TestMethod1(const MyClass val) {} .... static void TestMethod2(const int val) {} .... 

除了其他好的答案之外,我还会添加另一个为什么不把C风格的常量放到C#中的原因。 你说:

我们将参数标记为const,以确保其方法中的状态不会被改变。

如果const实际上做到了,那就太好了。 Const不这样做。 常量是一个谎言!

Const没有提供任何我可以实际使用的保证。 假设你有一个方法需要一个const的东西。 有两个代码作者:编写调用者的人和编写被调用 的人。 被调用者的作者已经使这个方法成为一个const。 两位作者可以假定对象是不变的?

没有。 被调用者可以自由地抛出const并且改变对象,所以调用者不能保证调用一个接受const的方法实际上不会改变它。 类似地,被调用者不能假定对象的内容在被调用者的动作中不会改变; 被调用者可以在const对象的非const别名上调用一些变异方法,现在所谓的const对象已经改变了

C风格的const不保证对象不会改变,因此被破坏。 现在,C已经有了一个弱types系统,在这个系统中,如果你真的想要的话,你可以重新解释一个double的types转换成inttypes,所以它对于const也有一个弱types系统。 但是C#被devise成拥有一个好的types系统,一个types系统,当你说“这个variables包含一个string”时,这个variables实际上包含了对string (或者null) 的引用 。 我们绝对不希望在types系统中使用C风格的“const”修饰符,因为我们不希望types系统是谎言 。 我们希望types系统是强大的,这样你可以正确地推理你的代码。

C中的Const是一个指导原则 ; 它基本上意味着“你可以相信我不要试图改变这个东西”。 这不应该在types系统中 ; types系统中的东西应该是关于你可以推理的对象的一个事实 ,而不是它的用法指南

现在,不要误解我的意思。 只是因为C中的const被深深打破并不意味着整个概念是无用的。 我希望看到的是在C#中的一些实际上正确有用的“const”注释forms,这是人类和编译器可以用来帮助他们理解代码的注释,并且运行时可以用来做自动平行化其他高级优化。

例如,想象一下,如果您可以围绕一大堆代码“画一个盒子”,并说“我保证这个代码块不会对该类的任何字段执行任何突变”,并且可以通过编译器检查。 或者画一个盒子,上面写着“这个纯粹的方法改变了对象的内部状态,但不是以任何方式在盒子外面观察”。 这样的对象不能自动安全的multithreading,但它可以自动记忆 。 我们可以将各种有趣的注释放在代码上,从而实现丰富的优化和更深入的理解。 我们可以比弱C风格的const注解做得更好。

不过,我强调这只是猜测 。 我们没有确切的计划把这种function放到任何假设的未来版本的C#中,如果甚至有一个,我们还没有宣布过这个或那个。 这是我希望看到的,以及即将到来强调多核计算可能需要的东西,但是这些都不能被解释为对C#的任何特定function或未来方向的预测或保证。

现在,如果你想要的仅仅是局部variables上的一个注释,这个variables是一个参数,表示“这个参数的值不会在整个方法中改变”,那么很容易做到这一点。 我们可以支持只读初始化的“只读”本地和参数,以及方法中编译时错误的改变。 由“使用”语句声明的variables已经是这样一个本地; 我们可以给所有的本地人和参数添加一个可选的注释,使它们像“使用”variables一样。 它从来不是一个高度优先的function,所以它从来没有实现过。

C#中没有const正确性的原因之一是因为它在运行时级别上不存在。 请记住,C#1.0没有任何function,除非它是运行时的一部分。

CLR没有const正确性概念的几个原因是例如:

  1. 它使运行时变得复杂。 除此之外,JVM也没有它,CLR基本上是作为一个项目来创build一个类似JVM的运行时,而不是类似于C ++的运行时。
  2. 如果在运行时级别具有常量正确性,则在BCL中应该具有const正确性,否则就.NET Framework而言,该function几乎毫无意义。
  3. 但是,如果BCL需要const正确性,则CLR上的每个语言都应该支持const正确性(VB,JavaScript,Python,Ruby,F#等)。这不会发生。

Const的正确性几乎只是C ++中的一种语言特性。 所以,它几乎归结为为什么CLR不需要检查exception(这是一个Java语言专用function)相同的论证。

另外,我不认为你可以在pipe理环境中引入这样一个基本types的系统特性,而不会破坏后向兼容性。 所以不要指望进入C#世界的const正确性。

我相信有两个原因C#是不正确的。

首先是可以理解的 。 很less有C ++程序员理解const的正确性。 const int arg的简单例子很可爱,但我也看到了char * const * const arg – 常量指针指向非常量字符的常量指针。 指向函数的常量正确性是一个全新的混淆级别。

第二个是因为类参数是通过值传递的引用。 这意味着已经有两个常量来处理,没有明显的语法 。 类似的绊脚石是集合(和集合的集合等)。

正确性是C ++types系统的重要组成部分。 它可以在理论上被添加到C#中,只能在编译时检查(不需要将其添加到CLR中,除非包含const成员方法的概念,否则不会影响BCL) 。

但是,我认为这是不太可能的:第二个原因(语法)很难解决,这会使第一个原因(理解性)成为更多的问题。

const在C#中的意思是“编译时常量”,而不是像C ++中的“只读,但可能是其他代码可以改变的”。 在C#中,C ++ const粗略模拟是readonly ,但只适用于字段。 除此之外,C#中没有C ++类似于const正确性的概念。

理由很难说清楚,因为有很多潜在的原因,但是我的猜测是希望保持语言的简单性,第二个是不确定的优点。