参考:
const : https://docs.microsoft.com/zh-cn/dotnet/csharp/programming-guide/classes-and-structs/constants
区别:
- readonly 关键字不同于 const 关键字。 const 字段只能在该字段的声明中初始化。 可以在字段声明和任何构造函数中多次分配 readonly 字段。 因此,根据所使用的构造函数,readonly 字段可能具有不同的值。 另外,虽然 const 字段是编译时常量,但 readonly 字段可用于运行时常量,如下面的示例所示:
一. const
1. 特点:
- 常量是不可变的值,在编译时是已知的,在程序的生命周期内不会改变。
- 仅 C# 内置类型(不包括 System.Object)可声明为 const
- 常量在声明时必须初始化。 例如:
class Calendar1
{
public const int Months = 12;
}
在此示例中,常量 Months 始终为 12,即使类本身也无法更改它。 实际上,当编译器遇到 C# 源代码中的常量标识符(例如Months )时,它直接将文本值替换到它生成的中间语言 (IL) 代码中。 因为运行时没有与常量相关联的变量地址
,所以 const 字段不能通过引用传递,并且不能作为l-value在表达式中显示。
- 常量像静态字段一样被访问,因为他的值对于所有类型的实例是一样的。你不需要用static关键字去声明他们。访问方式:
int birthstones = Calendar.Months;
二. readonly
1. 使用
readonly关键字是一个可在三个上下文中使用的修饰符:
(1)在字段申明中,readonly可以在字段声明和构造函数中多次分配、重新分配。构造函数退出后,不能分配 readonly 字段。
其中readonly在值类型和引用类型具有不同的含义:
-
由于值类型直接包含数据,因此属于 readonly 值类型的字段不可变
。 - 由于引用类型包含对其数据的引用,因此属于 readonly 引用类型的字段必须始终引用同一对象。 该对象不是不可变的。
readonly 修饰符可防止字段替换为引用类型的其他实例。 但是,修饰符不会阻止通过只读字段修改字段的实例数据。
(2) readonly struct,readonly 指示 struct 是不可变的。
(3)ref readonly
方法返回中,readonly 修饰符指示该方法返回一个引用,且不允许向该引用写入内容。
2. Readonly struct example
- struct 定义上的 readonly 修饰符声明该结构是不可变的 。
struct 的每个实例字段都必须被标记为 readonly
,如下例所示:
public readonly struct Point
{
public double X { get; }
public double Y { get; }
public Point(double x, double y) => (X, Y) = (x, y);
public override string ToString() => $"({X}, {Y})";
}
前面的示例使用只读自动属性来声明其存储。 该操作指示编译器为这些属性创建 readonly 支持字段。 还可以直接声明 readonly 字段:
public readonly struct Point
{
public readonly double X;
public readonly double Y;
public Point(double x, double y) => (X, Y) = (x, y);
public override string ToString() => $"({X}, {Y})";
}
3. Ref readonly return example
- ref return 上的 readonly 修饰符指示返回的引用无法修改。 下面的示例返回了一个对来源的引用。 它使用 readonly 修饰符来指示调用方无法修改来源:
private static readonly Point origin = new Point(0, 0);
public static ref readonly Point Origin => ref origin;
所返回的类型不需要为 readonly struct。 ref 能返回的任何类型都能由 ref readonly 返回。