default 是编译期确定的零值表达式,不调用构造函数:值类型返回全零位模式(如 int 为 0、bool 为 false),引用类型为 null,可空类型为 null,自定义 struct 各字段按类型取默认值。

default 不是“设默认值的快捷方式”,它是编译期确定的零值表达式,不调用构造函数、不执行任何初始化逻辑。
default(int)、default(string)、default(MyStruct) 各返回什么
结果完全由类型决定,编译器必须能推断出具体类型,否则报错 CS0441:
-
int、bool、DateTime等值类型 → 返回全零位模式:default(int)是0,default(bool)是false,default(DateTime)是new DateTime(0)(公元1年1月1日) -
string、object、自定义 class → 返回null -
int?、DateTime?等可空类型 → 返回null(注意:不是0或默认日期) - 自定义
struct→ 所有字段按各自类型取默认值(值类型字段为零,引用类型字段为null)
default(T) 和 new T() 为什么不能混用
语义完全不同,混淆会导致运行时异常或绕过关键约束:
-
default(T):不调用任何构造函数,对所有类型都合法(包括无参构造函数被禁用的 class) -
new T():必须存在可访问的无参构造函数,且会实际执行它;对ref struct直接编译失败(如Span<byte>) - 对带
readonly字段的struct:default(MyStruct)能通过编译(位清零),new MyStruct()会因未初始化readonly字段而报错 - 泛型方法中若写
T GetDefault<T>() => default;,传入string得null,传入int得0,行为不统一——业务上要 null 就显式写null as T或default(T?)
default 在泛型方法和 switch 表达式里的典型误用
看似简洁,实则隐藏类型歧义和兼容性风险:
- 泛型方法参数默认值写
T DoWork<T>(T value = default):C# 7.1+ 允许,但调用方若传入class类型,default就是null,可能触发 NRE;若传入struct,又变成零值,语义割裂 - switch 表达式中用
default => default:返回的是当前表达式推导出的类型零值,不是“兜底返回 null”——比如int? x = someValue switch { 1 => 5, _ => default };,default此处是null;但换成int x = ...,就是0 - C# 10+ 禁止对
ref struct使用default初始化(如Span<byte> s = default;编译失败),因为其生命周期无法被编译器安全验证
最常被忽略的一点:default 的“零值”是内存层面的位模式清零,不是逻辑意义上的“空对象”或“未初始化”。用它填充数组、作为泛型缓存初始值、或在高性能路径中避免 new 分配时很高效,但一旦涉及业务含义(比如“用户未设置”和“系统默认值”需区分),就必须换用明确的标记值或可空包装。


















