我了解了 const
和 static readonly
字段。我们有一些仅包含常量值的类。它们在系统中用于各种目的。所以我想知道我的观察是否正确:
对于所有公共内容,这种类型的常量值是否应始终是 static readonly
?而仅对 internal
/ protected
/ private
值使用 const
?
您有什么建议?甚至我也不应该使用 static readonly
字段,而应该使用属性吗?
当向其他程序集公开可能在以后版本中更改的值时,使用静态只读字段会更有优势。
例如,假设程序集 X
如下所示公开一个常量:
public const decimal ProgramVersion = 2.3;
如果汇编Y引用X并使用此常量,则当编译汇编Y时,值2.3将被嵌入到汇编Y中。这意味着,即使以后将X重新编译并将常量设置为2.4,Y仍将使用旧值2.3,直到重新编译Y。静态readonly字段可避免此问题。
另一种看待这个问题的方法是,任何可能在未来发生变化的值都不是常量的定义,并且因此不应表示为常量。
Const:Const就是“常量”,它是一个在编译时其值就确定了并且必须被赋值的变量。默认情况下,const是静态的,并且在整个程序中无法更改const变量的值。
Static ReadOnly:静态只读类型变量的值可以在运行时分配或者在编译时分配并在运行时更改。但是这个变量的值只能在静态构造函数中更改,并且不能再进行更改。它只能在运行时更改一次。
在 C# 中,const 和 static readonly 字段之间有一个小差别。
const 必须在编译时初始化值。
const 默认是静态的,需要使用常量值进行初始化,之后不能再修改。它不能与所有数据类型一起使用。例如 DateTime。无法与 DateTime 数据类型一起使用。
public const DateTime dt = DateTime.Today; //throws compilation error
public const string Name = string.Empty; //throws compilation error
public static readonly string Name = string.Empty; //No error, legal
readonly 可以被声明为静态的,但不是必需的。它不需要在声明时初始化。它的值可以通过构造函数进行赋值或更改。因此,readonly 字段的值可以被更改一次(无论是否为静态),而 const 无法更改。
const:
readonly:
如果你能提供编译时常量,请使用const
:
private const int Total = 5;
如果您需要在运行时评估值,请使用static readonly
:
private static readonly int GripKey = Animator.StringToHash("Grip");
private const int GripKey = Animator.StringToHash("Grip");
常量就像其名称所示,是不会改变的字段,通常在代码编译时静态定义。
只读变量是可以根据特定条件更改的字段。
它们可以在首次声明时像常量一样初始化,但通常在构造函数内部的对象构造期间进行初始化。
在上述条件下完成初始化后,它们将无法更改。
对我来说,静态只读听起来不太合适,因为如果它是静态的且永远不会改变,那么只需使用public const即可。如果它可以更改,则不是常量,然后根据您的需求,可以使用只读或普通变量。
另外,另一个重要的区别是常量属于类,而只读变量属于实例!
常量
静态只读
在重构期间,所有const都可以安全地转换为静态只读,但反之则不行,因为当转换代码时,某些静态只读变量可能在构造函数中初始化,导致代码出错。
const
中的大型字符串仍然只是一个单一的值,在代码中的多个位置引用,如此答案所述:https://dev59.com/emct5IYBdhLWcg3wjuEj#12004049。这里使用的语言:“编译后,无论在哪里使用常量,该值都将放置在编译代码的各个位置。”听起来像它使用了更多的内存。 - Digital Coyote还有一个区别,我认为上面没有提到:
const
和 static readonly
值在 Visual Studio IDE 中不会应用 CodeLens。
static
只读属性会应用 CodeLens。
我认为添加CodeLens非常有价值。
注意:目前使用的是Visual Studio 2022。
get
访问器下的逻辑更复杂,而不会改变成员使用者的“契约”。 - Jeppe Stig Nielsen
static readonly
:尝试在IEnumerator
中使用const
会触发无法到达的yield
,导致编译器出现可怕的“内部编译器错误”。虽然我没有在 Unity3D 之外测试过这段代码,但我相信这是 mono 或 .NET 的 问题。然而,这仍然是一个关于 c# 的问题。 - cregoxswitch-case
语句中,不能使用static readonly
作为case
变量,需要使用const
来替代。翻译后的内容保持原意,通俗易懂,无解释,无额外内容返回。 - Mostafiz Rahmanstatic readonly
不能用作属性参数。 - Dread Boy