静态只读与const - 不同的装配POV?

Roy*_*mir 17 c# static const readonly

关于这个问题有很多问题,但没有一个(除了一个,但仍然是一个短的)正在处理以下场景.

来自C#4书:

在此输入图像描述

马克还写道:

如果更改const的值,则需要重建所有客户端

题 :

1)为什么?是static readonlyconst- static

2)实际值保存在哪里

3)如何使一个领域static readonly实际上solve这个问题"落后于现场"?

Eri*_*ert 24

如果更改const的值,则需要重建所有客户端

这不是正确的解决方案.如果更改const的值,则它不是常量.根据定义,常量永远不会改变它们的价值.你会想法改变值常数,你正在做的事情逻辑上是不可能的手段,所以当然事情会打破; 你正在做一些你说你不会做的事情.如果你四处寻找编译器,当你这样做时会受到伤害,那么就不要再对编译器撒谎了.

黄金的价格不是一个常数.您的银行名称不是常数.程序的版本号不是常量.这些东西会改变,所以不要让它们成为常量.常数是像pi一样的东西,或者是金原子中的质子数.

变量是可以变化的东西- 这就是它们被称为"变量"的原因.常数是保持不变的东西.如果它可以变化,请将其变为变量.如果它是常数,则使其成为常数.它是如此简单.

这是为什么?static readonly和const都是静态的

当然.这与它有什么关系?C#中的"static"表示"命名元素与类型相关联,而不是与该类型的任何特定实例相关联." ("静态"因此是一个糟糕的术语选择; VB使用"共享"做得更好.)

名称是与类型还是实例相关联与名称是指常量还是变量的问题无关.

实际上值是在静态只读vsconst中保存的吗?

使用常量值时,无论在何处使用,该都将"烘焙".这是安全的, 因为它永远不会改变.它永远不会改变,因为它是不变的,这就是"常数"的含义.

使用变量时,每次都会在运行时查找变量的值."readonly"只表示"此变量只能在类构造函数或字段初始化程序中更改".它仍然是一个变量.(*)

如何使一个字段静态只读 - 实际上解决了场景背后的这个问题?

你还没有说明问题是什么,所以我不知道你要解决什么问题.


(*)只读字段被认为是构造函数之外的非常量值,因此不能改变可变值类型的只读字段,因此您不能将a取ref一个只读字段然后改变引用.


Mar*_*ell 22

不,const是一个const,而不是一个静态 - 它是一个特殊情况,具有不同的规则; 它在编译时设置(不是运行时),并且处理方式不同

这里的关键是以下意思:

var foo = SomeType.StaticValue;
Run Code Online (Sandbox Code Playgroud)

VS

var bar = SomeType.ConstValue;
Run Code Online (Sandbox Code Playgroud)

在第一种情况下,它从运行时读取值SomeType,即通过ldsfld; 但是,在第二种情况下,编译为值,即如果ConstValue恰好是123,则第二种情况:

var bar = 123;
Run Code Online (Sandbox Code Playgroud)

在运行时,它来自的事实SomeType 不存在,因为value(123)由编译器评估并存储.因此,它需要重建以获取新值.

更改为static readonly意味着SomeType保留" 从中加载值".

所以以下内容:

static int Foo()
{
    return Test.Foo;
}
static int Bar()
{
    return Test.Bar;
}
...
static class Test
{
    public static readonly int Foo = 123;
    public const int Bar = 456;
}
Run Code Online (Sandbox Code Playgroud)

编译为:

.method private hidebysig static int32 Bar() cil managed
{
    .maxstack 8
    L_0000: ldc.i4 0x1c8
    L_0005: ret 
}

.method private hidebysig static int32 Foo() cil managed
{
    .maxstack 8
    L_0000: ldsfld int32 ConsoleApplication2.Test::Foo
    L_0005: ret 
}
Run Code Online (Sandbox Code Playgroud)

注意,在Bar,直接ldc加载一个值(0x1c8 == 456),完全消失了.Test

为了完整性,const 用静态字段实现的,但是 - 它是一个文字字段,意思是:在编译时评估,而不是在运行时评估.

.field public static literal int32 Bar = int32(0x1c8)
.field public static initonly int32 Foo
Run Code Online (Sandbox Code Playgroud)


The*_*yan 6

1)const在编译期间刚刚使用您提供的值解析.虽然static readonly是一个静态变量.

2)static值通常存储在堆上称为High Frequency Heap的特殊区域.正如我之前所说,在编译时会替换consts.

3)使它static readonly解决问题因为你将在运行时读取变量值,而不是在编译时提供的值.