default 返回类型零值:值类型为全零位模式(如int为0),引用类型为null,可空类型为null,泛型依约束而定;不调用构造函数,与new T()语义不同。

default 关键字在 C# 中不是“设默认值的快捷方式”,而是类型系统在编译期就确定的**零值表达式**——它不调用构造函数,也不触发任何初始化逻辑,只返回该类型的“零状态”。
default 会返回什么值?看类型就知道
它的结果完全由上下文类型决定,编译器必须能推断出具体类型,否则报错 CS0441: 'default' cannot be used in this context because there is no type information available。
- 值类型(
int、DateTime、struct)→ 返回全零位模式:default(int)是0,default(DateTime)是new DateTime(0)(即公元1年1月1日) - 引用类型(
string、object、自定义类)→ 返回null - 可空类型(
int?)→ 返回null(注意:不是0) - 泛型类型参数
T→ 编译器按T的约束或实际传入类型决定;无约束时一律返回default(T)(可能是null或零值)
default(T) 和 new T() 完全不同
这是最容易混淆的点:default(T) 不调用任何构造函数,new T() 必须有无参构造函数且会执行它。
- 对
struct:两者结果常一样,但语义不同 ——default(MyStruct)是位清零,new MyStruct()是调用构造函数(哪怕你没写,编译器也生成了隐式无参构造) - 对
class:如果类没有无参构造函数,new T()编译失败;default(T)始终合法(返回null) - 对带
readonly字段的struct:default(MyStruct)能绕过字段初始化检查,new MyStruct()会因未初始化readonly字段而报错
泛型方法里用 default 要小心类型约束
当你写 T GetDefault<t>() => default;</t>,看起来简洁,但调用方传入 string 得到 null,传入 int 得到 0,行为不统一。如果业务上需要“所有类型都返回 null”,就得加约束:
static T? GetNullDefault<T>() where T : class => default;
或者更常见的是避免歧义,显式写清楚:
- 要零值 → 用
default(T),并确保调用方理解其语义 - 要 null → 显式写
default(T?)(当T是值类型)或null as T(当T是引用类型) - 要 new 实例 → 别用
default,老实用Activator.CreateInstance<t>()</t>或工厂
default 还能用在 switch 表达式和模式匹配里
从 C# 8 开始,default 在 switch 中不再是“兜底 case”,而是作为模式使用,比如:
var result = obj switch {
string s => s.Length,
int i => i * 2,
default => -1 // 匹配所有其他类型,包括 null
};注意这里 default 是模式,不是值表达式;它不返回零值,只是表示“其余所有情况”。别把它和 default(int) 混为一谈。
真正容易被忽略的是:在泛型约束宽松、又涉及跨平台序列化(如 System.Text.Json)时,default(T) 返回的零值可能和反序列化行为冲突 —— 比如 DateTime 的零值是公元1年,但很多 API 把它当成无效时间直接丢弃。这种边界情况,得靠单元测试覆盖,不能只信 default 的“默认”二字。


















