public class Color
{
public static Color Black = new Color(0, 0, 0);
public static Color White = new Color(255, 255, 255);
public static Color Red = new Color(255, 0, 0);
public static Color Green = new Color(0, 255, 0);
public static Color Blue = new Color(0, 0, 255);
private byte red, green, blue;
public Color(byte r, byte g, byte b) => (red, green, blue) = (r, g, b);
}
public class Color
{
public static readonly Color Black = new Color(0, 0, 0);
public static readonly Color White = new Color(255, 255, 255);
public static readonly Color Red = new Color(255, 0, 0);
public static readonly Color Green = new Color(0, 255, 0);
public static readonly Color Blue = new Color(0, 0, 255);
private byte red, green, blue;
public Color(byte r, byte g, byte b) => (red, green, blue) = (r, g, b);
}
15 回答
readonly
关键字与const
关键字不同 .const
字段只能在字段声明时初始化 . 可以在声明或构造函数中初始化readonly
字段 . 因此,readonly
字段可以具有不同的值,具体取决于所使用的构造函数 . 此外,虽然const
字段是编译时常量,但readonly
字段可用于运行时常量Short and clear MSDN reference here
其他一些事情
const int a
必须初始化
初始化必须在编译时
readonly int a
可以使用默认值,而无需初始化
初始化可以在运行时
常量类似于名称暗示,字段不会更改,通常在编译时在代码中静态定义 .
只读变量是在特定条件下可以更改的字段 .
当你第一次将它们声明为常量时,它们可以被初始化,但通常它们在构造函数内的对象构造期间被初始化 .
在初始化发生后,在上述条件下,它们无法更改 .
静态只读对我来说是一个糟糕的选择,因为它是静态的并且它永远不会改变,所以只需使用它就是公共const,如果它可以改变那么它不是常数然后,根据你的需要,你可以使用read - 只是一个常规变量 .
另外,另一个重要的区别是常量属于类,而只读变量属于实例!
public static readonly
字段有点不寻常;public static
属性(仅使用get
)会更常见(可能由private static readonly
字段支持) .const
值直接刻录到呼叫站点;这是双刃:如果在运行时获取值,则可能无法从config获取
如果更改const的值,则需要重建所有客户端
但它可以更快,因为它避免了方法调用...
......无论如何,JIT有时可能已将其内联
如果值将 never 更改,则const很好 -
Zero
等进行合理的consts; p除此之外,static
属性更常见 .如果Consumer在不同的程序集中,我会使用
static readonly
. 将const
和Consumer放在两个不同的程序集中是shoot yourself in the foot的好方法 .Const :const变量值必须与声明一起定义,之后它不会改变 . const are implicitly static so without creating class instance we can access them. 这在编译时有一个值
ReadOnly :我们可以在声明以及在运行时使用构造函数时定义的只读变量值 . readonly变量无法访问没有类实例 .
Static readonly :静态只读变量值我们可以在声明时定义,只能通过静态构造函数来定义,但不能与任何其他构造函数一起定义 . 这些变量也可以在不创建类实例的情况下访问(作为静态变量) .
如果我们必须使用不同程序集中的变量,静态只读将是更好的选择 . 请检查下面链接中的完整详细信息
https://www.stum.de/2009/01/14/const-strings-a-very-convenient-way-to-shoot-yourself-in-the-foot/
参考:c-sharpcorner
Static Read Only :可以在运行时通过
static
构造函数更改值 . 但不是通过成员函数 .Constant :默认为
static
. Value 不能从任何地方改变(Ctor,Function,runtime等no-where) .Read Only :可以在运行时通过构造函数更改值 . 但不是通过成员函数 .
你可以看一下我的回购:C# property types .
C#.Net中const和静态只读字段之间存在细微差别
const必须在编译时用值初始化 .
const默认是静态的,需要用常量值初始化,以后不能修改 . 它不能与所有数据类型一起使用 . 对于前日期时间 . 它不能与DateTime数据类型一起使用 .
readonly可以声明为static,但不是必需的 . 没有必要在申报时初始化 . 可以使用构造函数一次分配或更改其值 . 所以有可能改变readonly字段的值一次(无关紧要,如果它是静态的),这是const不可能的 .
const
和readonly
是相似的,但它们并不完全相同 .const
字段是编译时常量,表示该值可以在编译时计算 .readonly
字段允许在构造类型期间必须运行某些代码的其他方案 . 构建后,无法更改readonly
字段 .例如,
const
成员可用于定义以下成员:因为像3.14和0这样的值是编译时常量 . 但是,请考虑您定义类型并希望提供一些预制实例的情况 . 例如,您可能希望定义一个Color类并为常见颜色(如Black,White等)提供“常量” . 使用const成员不可能这样做,因为右侧不是编译时常量 . 可以使用常规静态成员执行此操作:
但是,通过交换黑白值,没有什么能阻止Color的客户端使用它 . 不用说,这会导致Color类的其他客户端惊慌失措 . “只读”功能解决了这种情况 .
通过在声明中简单地引入
readonly
关键字,我们保留了灵活的初始化,同时防止客户端代码混乱 .有趣的是,const成员总是静态的,而readonly成员可以是静态的,也可以不是静态的,就像常规字段一样 .
可以将单个关键字用于这两个目的,但这会导致版本控制问题或性能问题 . 假设我们为此(const)使用了一个关键字,开发人员写道:
而另一个开发人员编写的代码依赖于A:
现在,生成的代码能否依赖于A.C是编译时常量的事实?即,A.C的使用是否可以简单地用值0代替?如果对此说“是”,那么这意味着A的开发人员无法改变A.C初始化的方式 - 这将未经许可将A的开发人员联系起来 .
如果你对这个问题说“不”,那么就会错过重要的优化 . 也许A的作者肯定A.C永远是零 . const和readonly的使用允许A的开发者指定意图 . 这样可以获得更好的版本控制行为和更好的性能 .
常量:
值应在声明时给出
编译时间常数
只读:
值可以在声明时或在运行时使用构造函数给出 . 值可以根据使用的构造函数而变化 .
运行时常数
我的偏好是尽可能使用 const ,如上所述,这仅限于文字表达或不需要评估的东西 .
如果我对这个限制感到热烈,那么我会回避 static readonly ,但有一点需要注意 . 我通常会使用带有getter和后备 private static readonly 字段的公共静态属性,如Marc提到here .
这只是对其他答案的补充 . 我不会重复它们(现在四年后) .
在某些情况下,
const
和非const具有不同的语义 . 例如:打印出
True
,而:写道
False
.原因是方法x.Equals有两个重载,一个接收
short
(System.Int16
),另一个接收object
(System.Object
) . 现在问题是一个或两个是否适用于我的y
参数 .当
y
是编译时常量(文字),const
情况时,如果int
是常量,并且C#编译器验证其值是否在内,则确实存在从int
到_258353的隐式转换变得很重要 .short
的范围(42
是) . 请参阅C#语言规范中的Implicit constant expression conversions . 因此必须考虑两种重载 . 重载Equals(short)
是首选(任何short
是object
,但并非所有object
都是short
) . 所以y
转换为short
,并使用该重载 . 然后Equals
比较两个相同值的short
,并给出true
.当
y
不是常量时,不存在从int
到short
的隐式转换 . 这是因为一般情况下int
可能太大而无法适应short
. (显式转换确实存在,但我没有说Equals((short)y)
,所以这不相关 . )我们看到只有一个重载适用,Equals(object)
. 所以y
被装箱到object
. 然后Equals
将System.Int16
与System.Int32
进行比较,并且由于运行时类型甚至不同意,因此将产生false
.我们得出结论,在一些(罕见的)情况下,将
const
类型成员更改为static readonly
字段(或者在可能的情况下将其他方式更改)可以更改程序的行为 .需要注意的一点是const仅限于原始/值类型(异常是字符串)
当向其他程序集公开可能在更高版本中更改的值时,静态只读字段是有利的 .
例如,假设程序集
X
公开一个常量,如下所示:如果程序集
Y
引用X
并使用此常量,则值2.3将在编译时被烘焙到程序集Y
中 . 这意味着如果X
稍后在常量设置为2.4的情况下重新编译,Y
仍将使用旧值2.3,直到重新编译Y
. 静态只读字段可以避免此问题 .另一种看待这种情况的方法是,根据定义,未来可能发生变化的任何值都不是恒定的,因此不应该表示为一个 .