TEngine学习

发布于:2025-07-18 ⋅ 阅读:(23) ⋅ 点赞:(0)

关于静态类中的静态变量赋值:

   public static class ActorEventDefine
   {
       public static readonly int ScoreChange = RuntimeId.ToRuntimeId("ActorEventDefine.ScoreChange");
       public static readonly int GameOver = RuntimeId.ToRuntimeId("ActorEventDefine.GameOver");
       public static readonly int EnemyDead = RuntimeId.ToRuntimeId("ActorEventDefine.EnemyDead");
       public static readonly int PlayerDead = RuntimeId.ToRuntimeId("ActorEventDefine.PlayerDead");
       public static readonly int AsteroidExplosion = RuntimeId.ToRuntimeId("ActorEventDefine.AsteroidExplosion");
       public static readonly int EnemyFireBullet = RuntimeId.ToRuntimeId("ActorEventDefine.EnemyFireBullet");
       public static readonly int PlayerFireBullet = RuntimeId.ToRuntimeId("ActorEventDefine.PlayerFireBullet");
   }

在 Unity 中,static readonly 字段的赋值时机遵循 .NET 的规则:

当第一次访问 ActorEventDefine 类本身或其中的任何成员时,CLR 会执行该类的类型初始化(Type Initializer)

此时,所有 static readonly 字段会按顺序执行赋值(即调用 RuntimeId.ToRuntimeId(...))。

关键点:

  • 延迟初始化:直到首次访问时才会执行,而非游戏启动时立即执行。

  • 线程安全:CLR 保证静态构造函数是线程安全的,多线程访问时不会重复初始化。

  • 性能:由于 RuntimeId.ToRuntimeId 可能是计算密集型操作,首次访问可能会有轻微延迟,但后续访问无额外开销。


具体流程:

  1. 首次访问触发
    当你第一次通过代码访问 ActorEventDefine.ScoreChange 或其他字段,或显式使用 ActorEventDefine 类时(例如在初始化时注册事件监听),CLR 会检查该类是否已初始化。

  2. 静态构造函数执行
    由于代码中没有显式定义 static ActorEventDefine() 构造函数,编译器会自动生成一个隐式的静态构造函数,其中包含所有 static readonly 字段的赋值逻辑。

  3. 字段初始化顺序
    所有 static readonly 字段会按代码中的顺序初始化(ScoreChangeGameOver → ...),且仅执行一次,后续访问直接复用已初始化的值

出处:

根据 Microsoft C# 编程指南官方文档 的说明:

“如果未提供静态构造函数来初始化静态字段,会将所有静态字段初始化为其默认值。如果静态构造函数类中存在静态字段变量初始值设定项,它们将以在类声明中显示的文本顺序运行。初始值设定项紧接着静态构造函数之前运行。”

这意味着,当你没有显式定义一个 static ActorEventDefine() 构造函数时,编译器会自动生成一个隐式的静态构造函数(即“类型构造器”),并将所有 static readonly 字段的初始化代码插入到这个构造器中,按声明顺序执行。

此外,CLR via C# 一书中也明确指出:

“当你使用内联语法初始化静态字段时,C# 编译器会将这些初始化语句移动到它自动生成的类型构造器中。”

因此,“编译器会自动生成一个隐式的静态构造函数”这一行为在官方文档和技术规范中均有明确依据,并非推测。


网站公告

今日签到

点亮在社区的每一天
去签到