当前位置: 首页 > ops >正文

【原理】C#构造函数可以标记为Static吗

【从UnityURP开始探索游戏渲染】专栏-直达

  • 实例构造函数(Instance Constructor)不能标记为static
  • 但C#提供了一种特殊的‌ 静态构造函数(Static Constructor)专门用于初始化静态成员。
  • 下面依次介绍他们:

1. ‌实例构造函数(不能标记为static)‌

  • 用于初始化‌实例成员‌。
  • 每次创建类的新实例时调用。
  • 不允许‌使用static关键字修饰。
csharp
public class MyClass {
// 实例构造函数(正确)public MyClass() {
// 初始化实例成员}
//  ❌ 错误:实例构造函数不能标记为static// public static MyClass() { ... }
}

2. ‌静态构造函数(隐式static)‌

  • 用于初始化‌静态成员‌。
  • 在整个程序生命周期内‌最多自动调用一次‌(在类首次被使用时触发)。
  • 必须满足以下语法:
    • 使用static关键字。
    • 不能有访问修饰符‌(如publicprivate),默认为private
    • 不能有参数‌。
    • 类中最多只能有一个静态构造函数。
csharp
public class MyClass {static MyClass() {
// 初始化静态成员}
}

关键总结

特性实例构造函数静态构造函数
关键字static(不能标记为static必须使用static
调用时机每次创建实例时调用类首次使用时自动调用(仅一次)
参数可以有参数不能有参数
访问修饰符支持(如publicprivate不允许‌(默认为private
用途初始化实例成员初始化静态成员

何时使用静态构造函数?

当类中的静态成员(如静态字段)需要复杂的初始化逻辑(例如读取配置文件或构建静态数据结构)时使用:

csharp
public class Logger {public static string LogPath { get; }static Logger() {LogPath = LoadLogPathFromConfig();// 复杂初始化}private static string LoadLogPathFromConfig() { ... }
}

错误示例

csharp
public class MyClass {
//  ❌ 编译错误:实例构造函数不能是静态的public static MyClass() { ... }//  ❌ 编译错误:静态构造函数不能有访问修饰符public static MyClass() { ... }//  ❌ 编译错误:静态构造函数不能有参数static MyClass(string param) { ... }
}

结论‌:

普通构造函数(实例构造函数)‌不能‌标记为static,但C#提供了专门的‌静态构造函数语法‌(使用static关键字且无访问修饰符/参数)来初始化静态成员。两者设计目的和调用机制完全不同。

使用示例

  • 基础使用场景(初始化静态成员)静态构造函数常用于初始化类的静态字段,例如统计类实例数量:
csharp 
public class Logger
{public static int InstanceCount;public static string LogDirectory;static Logger(){InstanceCount = 0;LogDirectory = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData),"AppLogs");Directory.CreateDirectory(LogDirectory);}
}
  • 当首次访问Logger类时,会自动创建日志目录并初始化计数器。

  • 配置加载示例适合加载只需执行一次的配置文件:

csharp
public class AppConfig
{public static readonly Dictionary<string, string> Settings;static AppConfig(){Settings = new Dictionary<string, string>();var config = ConfigurationManager.AppSettings;foreach (var key in config.AllKeys){Settings.Add(key, config[key]);}}
}
  • 该构造函数在程序首次使用配置时自动加载。

  • 复杂初始化场景处理相互依赖的静态字段初始化:

csharp
public class A
{public static int X = B.Y + 1;static A() { }
}public class B
{public static int Y = A.X + 1;static B() { }
}
  • 运行时能正确处理这种交叉引用关系。

关键特性说明:

  • 每个类只能有一个静态构造函数
  • 不能包含访问修饰符或参数
  • 在以下情况自动调用:创建第一个实例前访问任何静态成员前
  • 执行时机由CLR控制,不可显式调用

特殊注意事项:

  • 当同时存在静态构造函数和静态字段初始化时,字段初始化器会先执行。例如:
csharp
public class Test
{public static Test t = new Test();static Test() => Console.WriteLine("静态构造");public Test() => Console.WriteLine("实例构造");
}
// 输出顺序:实例构造 -> 静态构造

典型应用场景:

  • 初始化静态字典/集合
  • 注册事件处理器
  • 加载本地化资源
  • 建立数据库连接池

注意

  • 静态构造函数中应避免抛出异常,否则会导致TypeInitializationException

【从UnityURP开始探索游戏渲染】专栏-直达
(欢迎点赞留言探讨,更多人加入进来能更加完善这个探索的过程,🙏)

http://www.xdnf.cn/news/17966.html

相关文章:

  • Oracle Undo Tablespace 使用率暴涨案例分析
  • Java 方法引用详解
  • Vue.js 路由/redirect重定向刷新机制详解
  • 新的“MadeYouReset”方法利用 HTTP/2 进行隐秘的 DoS 攻击
  • linux-高级IO(上)
  • 数据结构4线性表——顺序栈
  • Microsoft WebView2
  • Java 大视界 -- 基于 Java 的大数据分布式计算在气象灾害预警与应急响应中的应用
  • 【lucene】SegmentInfos
  • 系统思考—啤酒游戏经营决策沙盘认证
  • 论文推荐|迁移学习+多模态特征融合
  • 二叉树的三种遍历方法
  • ZKmall开源商城的数据校验之道:用规范守护业务基石
  • 【论文笔记】STORYWRITER: A Multi-Agent Framework for Long Story Generation
  • lcx、netcat、powercat--安装、使用
  • [go] 桥接模式
  • 分布式存储与存储阵列:从传统到现代的存储革命
  • Tello无人机与LLM模型控制 ROS
  • 安全审计-iptales防火墙设置
  • 立体匹配中的稠密匹配和稀疏匹配
  • 教材采购管理系统(java)
  • 力扣(接雨水)——基于最高柱分割的双指针
  • Python - 100天从新手到大师:第十一天常用数据结构之字符串
  • Flink Stream API 源码走读 - 总结
  • 双指针和codetop复习
  • Day56 Java面向对象10 方法重写
  • Vue组件基础解析
  • [系统架构设计师]系统质量属性与架构评估(八)
  • Python语言---OrangePi全志H616
  • MySQL锁机制:悲观锁VS乐观锁详解