is 和 as 在 IL 层面的本质区别
is运算符只做类型检查,返回
bool;
as运算符尝试转换,成功返回目标引用,失败返回
null(对引用类型)或
default(T)(对可空值类型)。两者在 IL 中都调用
isinst指令,但
as多一步赋值操作——这步开销极小,几乎可忽略。
连续使用 is + 强制转换时性能更差
常见反模式:
if (obj is string) { var s = (string)obj; ... }。这会触发两次类型检查:一次 is,一次强制转换中的隐式
isinst。JIT 通常不会优化掉第二次检查。 正确写法是直接用
as:
var s = obj as string; if (s != null) { ... }
对值类型(如 int?)需注意:
as不支持非可空值类型,只能用于引用类型或可空值类型 如果后续必须用非空值类型,且已知安全,可用
obj as string ?? throw new InvalidOperationException(),避免重复检查
as 在热路径中略快,但差异通常不构成瓶颈
单次调用下,
as比
is+ 强转快约 10%–15%(实测 .NET 6+ x64),因为省去一次运行时类型验证。但这个差距只有在每秒百万级类型判断时才可能被观测到。 真实业务代码中,类型检查往往不是热点,IO、内存分配、锁竞争才是瓶颈 过度纠结
isvs
as的微秒级差异,不如检查是否误用了装箱(比如对
int频繁
is object) 使用
as时务必判空,否则可能引入
NullReferenceException,调试成本远高于那几纳秒
pattern matching(C# 7+)改变了权衡逻辑
现代 C# 推荐用模式匹配替代裸
is或
as,例如
if (obj is string s) { /* s 已声明且非 null */ }。它在语义上等价于 as+ 判空,但由编译器生成更紧凑的 IL,且变量作用域清晰。 这种写法既安全又高效,JIT 可对其做更好优化 对继承链深的对象,
is Type t和
as Type性能表现一致,都依赖 CLR 的类型系统缓存 注意:模式匹配在结构体上会产生复制,若类型较大(如含数组字段),
as(仅适用引用类型)反而更轻量
实际编码中,优先选语义清晰的写法,而不是预设“哪个更快”。真正影响性能的,往往是类型检查发生的次数和上下文,而不是运算符本身。
