常量与 readonly 字段
区分 const 与 static readonly。
常量与 readonly 字段 是 CoddyKit 上的免费 C# Academy 课时。 这是第 3 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 C# Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 C# Academy 课程共包含 4 节课。
让值保持固定的两种方式
C# 提供 const 和 readonly,用于表示不应更改的值。它们看起来相似,但行为却非常不同。本课将比较二者。
using System;
class Config
{
public const double Pi = 3.14159;
public static readonly DateTime StartedAt = DateTime.Now;
}
class Program
{
static void Main()
{
Console.WriteLine("Pi = " + Config.Pi);
}
}const:编译时常量
声明 const 时必须为其赋予字面量值,并且该值会在编译时直接嵌入。它会隐式成为静态成员。
using System;
class Circle
{
public const double Pi = 3.14159;
public static double Area(double r) => Pi * r * r;
}
class Program
{
static void Main()
{
Console.WriteLine(Circle.Area(2).ToString("0.00"));
}
}const 必须是字面量
由于 const 会在编译时解析,因此它只能保存常量表达式:数字、字符串、布尔值或其他 const。
using System;
class Limits
{
public const int MaxRetries = 3;
public const int Timeout = MaxRetries * 1000; // const expression OK
}
class Program
{
static void Main()
{
Console.WriteLine(Limits.MaxRetries + ", " + Limits.Timeout);
}
}readonly:运行时常量
readonly 字段只能设置一次,可以在声明时或构造函数中设置,之后便不能更改。它的值可以在运行时计算。
using System;
class Session
{
public readonly string Id;
public Session(string id)
{
Id = id; // allowed: inside constructor
}
}
class Program
{
static void Main()
{
var s = new Session("abc-123");
Console.WriteLine("Session: " + s.Id);
}
}readonly 可以使用运行时值
与 const 不同,readonly 字段可以保存只有在程序运行时才能确定的值,例如生成的 id 或当前时间。
using System;
class Order
{
public readonly Guid OrderId;
public Order()
{
OrderId = Guid.NewGuid();
}
}
class Program
{
static void Main()
{
var o = new Order();
Console.WriteLine("Has id: " + (o.OrderId != Guid.Empty));
}
}静态 readonly
将 static readonly 结合使用,可以表示一个在运行时计算一次、供整个类使用的值。当值不是字面量时,这通常是替代 const 的方式。
using System;
class AppInfo
{
public static readonly string[] Roles = { "admin", "user", "guest" };
}
class Program
{
static void Main()
{
Console.WriteLine("Roles: " + Roles());
}
static int Roles() => AppInfo.Roles.Length;
}常量跨程序集为何可能带来风险
由于 const 值会在编译时内联到调用代码中,因此更改库中的公共 const 后,必须重新编译所有调用方。使用 static readonly 可以避免这一问题。
using System;
class Lib
{
public const int Version = 2; // inlined into callers
public static readonly int Build = 100; // read at runtime
}
class Program
{
static void Main()
{
Console.WriteLine(Lib.Version + "." + Lib.Build);
}
}两者都不能重新赋值
初始化后,const 和 readonly 字段都不能再更改。尝试这样做会导致编译错误。
using System;
class Demo
{
public const int A = 10;
public readonly int B;
public Demo() { B = 20; }
// A = 11; // would not compile
// B = 21; // would not compile outside constructor
}
class Program
{
static void Main()
{
var d = new Demo();
Console.WriteLine(Demo.A + ", " + d.B);
}
}如何在两者之间选择
对于真正不会改变的字面量(圆周率、MaxInt),请使用 const。当值在运行时计算,或可能因实例而异时,请使用 readonly。
using System;
class Physics
{
public const double Gravity = 9.81; // universal literal
public readonly double Mass; // per object
public Physics(double mass) { Mass = mass; }
public double Weight() => Mass * Gravity;
}
class Program
{
static void Main()
{
var p = new Physics(10);
Console.WriteLine("Weight: " + p.Weight());
}
}readonly 引用注意事项
readonly 锁定的是字段,而不是它所指向的对象。readonly 列表引用不能重新赋值,但其内容仍然可以改变。
using System;
using System.Collections.Generic;
class Cart
{
public readonly List<string> Items = new List<string>();
}
class Program
{
static void Main()
{
var c = new Cart();
c.Items.Add("Pen"); // allowed: mutating the object
c.Items.Add("Book");
Console.WriteLine("Items: " + c.Items.Count);
}
}综合运用
典型的类会使用 const 保存固定字面量,并使用 readonly 保存对象构造时针对每个实例确定的值。
using System;
class Account
{
public const decimal MinBalance = 0m;
public readonly string Owner;
public Account(string owner)
{
Owner = owner;
}
}
class Program
{
static void Main()
{
var a = new Account("Rin");
Console.WriteLine(a.Owner + " min=" + Account.MinBalance);
}
}快速检查
请测试您对常量与 readonly 区别的理解。
回顾
const 是编译时字面量,隐式为静态成员,并会内联到调用方中。readonly 只能在声明时或构造函数中设置一次,但可以使用运行时值。真正的字面量请使用 const,运行时计算的共享值请使用 static readonly,并记住 readonly 锁定的是引用,而不是对象。
using System;
class Demo
{
public const int Max = 100;
public readonly int Created;
public Demo(int c) { Created = c; }
}
class Program
{
static void Main()
{
var d = new Demo(7);
Console.WriteLine(Demo.Max + ", " + d.Created);
}
}常见问题解答
「常量与 readonly 字段」课时是免费的吗?
是的 — 「常量与 readonly 字段」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 C# Academy 课程的其余内容,请升级到 CoddyKit PRO。 C# Academy 课程共包含 4 节课。
「常量与 readonly 字段」这节课中我会学到什么?
区分 const 与 static readonly。 你通过在浏览器中直接运行的动手代码来练习 C# Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。
学习 C# Academy 需要有经验吗?
无需任何先前经验。CoddyKit 上的 C# Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 3 节课,共 4 节。
「常量与 readonly 字段」课时需要多长时间?
大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。
我能在这节 C# Academy 课中编写并运行代码吗?
能。每节 C# Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。
此课程中的所有课时
- 静态方法与字段
- 用于实用功能的静态类
- 常量与 readonly 字段
- 静态设计与实例设计