如何在C#中声明本地常量?

46

如何在C#中声明本地常量?

与Java类似,您可以执行以下操作:

public void f(){
  final int n = getNum(); // n declared constant
}

如何在C#中实现相同的功能?我尝试使用readonlyconst,但似乎都不起作用。

任何帮助将不胜感激。

谢谢。


16
在我短暂使用 C# 的时间里,这是最让人恼火的缺失。在 C++ 中,我经常对局部变量使用 const 来确保自己的安全、理智和可读性。 - pauldoo
https://dev59.com/mHRB5IYBdhLWcg3w-8Lo - Mauricio Scheffer
@MauricioScheffer,感谢提供链接。不过现在如果我需要为.NET编写代码,我肯定会使用F#。 :-) - missingfaktor
7个回答

28

25
好的,那很糟糕。:/ - Mateen Ulhaq
12
残酷。我不仅应该得到支持,这应该成为默认设置。 - andyczerwonka
5
finalconst有不同的含义。在C#中,const值必须在编译时就已知。真正的问题是C#不支持局部的readonly变量,这很遗憾,因为它们会很方便。 - Nick
在 C# 中,const 必须被赋予编译时已知或可在编译时计算的常量值。但在运行时,对于属性类似 readonly 的东西,也可以应用于局部变量,这样做没有问题,我错了吗?据我所知,在 C#中,readonly 是针对属性强制执行的(即使它也是编译时的错误)。例如,我们可以有本地 var readonly id = GetId();var const id = -1;,后者基本上是一个文本,它会被其值所替代。 - Paul-Sebastian Manole
不确定为什么这个答案被接受了。对我来说,@TamasCzinege的答案看起来解释得很清楚,也很有帮助。应该查看这个答案https://dev59.com/1nI-5IYBdhLWcg3wBjZR#2054775。 - Yas Ikeda
显示剩余2条评论

21

将你的本地变量声明为迭代变量。迭代变量是只读的。(你没有要求一个漂亮的解决方案)。

public void f() 
{
  foreach (int n in new int[] { getNum() }) // n declared constant
  {
    n = 3; // won't compile: "error CS1656: Cannot assign to 'n' because it is a 'foreach iteration variable'"
  }
}

16
了解,但上帝保证,我永远不会这么做。 - missingfaktor
2
这太棒了!这个hack太丑陋了,我甚至没有想过它。但我一定会将其用作代码片段来检查我的代码,你知道的,暂时将var index=GetNum()更改为foreach以强制编译器检查我的代码。 - Sergey.quixoticaxis.Ivanov
哎呀,我还在拼命琢磨这个问题,正在认真考虑使用这个hack。真是一个非常不正规的方法啊;-) - Xan-Kun Clark-Davis

8

我不确定为什么readonlyconst 对你没起作用,因为这些是你需要的关键词。如果你有一个字面量(除了数组字面量),则使用const,否则,请使用readonly

public void f()
{
    const int answer = 42;
}

private readonly int[] array = new int[] { 1, 2, 3, 4 };
private readonly DateTime date = DateTime.Now;
public void g()
{
    Console.WriteLine(date.ToString());   
}

readonly 只适用于类级别(也就是只能应用于字段)。另外,由于 const 需要一个字面量,它本质上是静态的,而 readonly 字段可以是静态的或实例的。


2
需要注意的是,创建一个只读的引用类型实例仅意味着引用本身无法更改;对象仍然可以按常规方式修改(除非该类型是不可变的,如String)。 - Kevin Kibler
3
回答你的问题很简单——在给定的示例中,const和readonly都不适用。 - greenoldman

6
截止到2018年10月2日,在C#中无法有只读的本地变量,但是有一个开放的提案正在进行讨论,旨在实现这个功能。

这篇文章提供了有用的概述。


4

有一种解决方法需要使用ReSharper。您无法获得只读本地变量,但是您至少可以检测到已经变异的变量并将它们以不同的颜色显示。

使用“字体和颜色”项Resharper Mutable Local Variable Identifier

对于我来说,本地变量会被涂成灰色,而我选择了加粗的白色来表示已经变异的变量(这适用于暗色主题)。这意味着任何写入超过一次的变量显示为亮色与普通变量相比。然后您可以尽可能避免变异变量,如果该方法确实需要一个则它至少会被突出显示。


它对我不起作用。它只显示循环计数器为不可变的,其他所有内容都是可变的,无论写入多少次。我猜我的 Resharper 太旧了 :-) - Xan-Kun Clark-Davis
@Xan-KunClark-Davis 它并不显示什么是可变的,它显示的是什么被改变了。任何只写入一次的内容都会看起来正常。任何写入两次或更多次的内容都会被突出显示。(哦,我猜你说“无论写入多少次”)。你确定吗?像 int x = 5; x = 3; 这样的内容,x 应该会改变颜色。我想这可能是版本问题,是的。 - Dave Cousineau
@ Sahuagin 是的,我明白你必须将它反转,所有本地变量都会被突出显示,所有可变变量都会再次“正常化”,但是,颜色仍然没有改变。我会再试一次干净的项目。 - Xan-Kun Clark-Davis
好的,我打开了一个新的工作区并再次尝试,它可以工作了!真正的魔法 :-) 唯一的问题是,有一个行为我不理解,但在这里解释会太复杂。 - Xan-Kun Clark-Davis
哇塞!我现在真的很喜欢它 :-) - Xan-Kun Clark-Davis

1
在你提供的例子中,你需要将变量声明为static,因为你正在使用方法调用进行初始化。如果你使用常量值(如42)进行初始化,则可以使用const。对于类、结构体和数组,readonly应该可以工作。

8
请注意,您不能在变量上使用static关键字,只能在成员上使用。 - Tamas Czinege

0
const关键字用于修改字段或局部变量的声明。
来自MSDN
由于C#无法强制执行“const正确性”(如c++),因此我认为它并不是非常有用。由于函数的作用域非常狭窄,因此很容易不会失去监督。

我必须指出,然而Eric Dahlvang仍然正确地指出了为什么const在你的情况下不起作用。 - Johannes Rudolph
1
由于函数的作用域非常狭窄,因此很容易不会失去监督。那么为什么其他语言如C++和Java提供这样的机制呢? - missingfaktor
不了解Java,但C++可以在引用上强制使用真正的const,而C#则不能。我从未见过除C++之外的任何地方局部使用const。 - Johannes Rudolph
“由于函数的作用域非常狭窄,因此很容易不会失去监督。” — 这并不是真的。在函数式编程中,尽可能多地使用常量实际上是一个主要特点。 — “我从未见过除了C++之外的任何地方都使用本地const” — 当我编写C++时,我一直在使用const。对于参数、返回值、局部变量,所有可以声明为const的都声明为const。 - Martin
我不能同意这个说法,即它没有用。事实上,它非常有用。如果我看到一个本地的const变量,我立刻知道以后不会有惊喜。它对可读性有很大帮助。 - Christian Rizov

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接