is只判断类型不转换,as尝试转换失败返回null;二者组合使用会导致重复类型检查,C# 7+推荐用模式匹配if(obj is string s)一次性完成判断与赋值。

is 操作符只判断类型,不转换
is 用于运行时检查对象是否属于某个类型(或其派生类型),返回 true 或 false,**不会执行任何类型转换**。它不抛异常,也不改变原变量值。
常见错误是以为 is 后能直接用转型结果:
if (obj is string) {
Console.WriteLine(obj.Length); // 编译错误!obj 还是 object 类型
}正确写法必须显式转换(或用模式匹配):
- 老写法:
if (obj is string) { string s = (string)obj; ... } - C# 7+ 推荐:
if (obj is string s) { Console.WriteLine(s.Length); }—— 这里s是新声明的局部变量,不是obj被“改类型”了
as 操作符尝试转换,失败返回 null
as 尝试将对象引用转换为指定引用类型或可空类型。**仅适用于引用类型和可空值类型**;对非可空值类型(如 int、DateTime)使用会编译报错。
它不抛异常,转换失败时返回 null(对可空值类型返回 null 值)。但要注意:如果目标类型是 string、object 等引用类型,源为 null 时也返回 null,无法区分“本来就是 null”和“转换失败”。
- 合法:
var s = obj as string;(obj是object) - 非法:
var i = obj as int;→ 编译错误,int是非可空值类型 - 合法(可空):
var i = obj as int?;
is 和 as 组合使用容易引发两次类型检查
这是性能和可读性上最常被忽略的问题。下面这段代码效率低且冗余:
一套专门解决旅行社网上预定、发布、管理线路的强大系统,系统基于ASP+ACCESS数据库开发,功能强大,操作方便,系统设计完全符合旅行社的运做模式。系统着重体现易操作性,只要您会打字,便操作。系统由以下几个模块组成:1、线路的类别发布和管理2、线路的发布和管理3、线路的属性管理(是精品线路、还是普通线路)4、客户预定线路订单管理,人性化的区分为未处理订但和处理订单5、线路查询功能6、网站留言功能,
if (obj is string) {
string s = obj as string; // 又做了一次运行时类型检查
Process(s);
}CLR 在 is 和 as 中都会执行相同的类型判定逻辑,相当于重复工作。C# 7+ 的模式匹配语法正是为解决这个而生:
- ✅ 推荐:
if (obj is string s) Process(s);—— 一次检查,一次赋值 - ✅ 或者直接用
as+ 空检查:string s = obj as string; if (s != null) Process(s); - ❌ 避免
is后紧跟as,除非你明确需要中间的布尔判断逻辑
值类型场景下 as 完全不可用,is 仍可用
对值类型(如 int、Guid、自定义 struct),as 不能用,编译器直接拒绝。但 is 可以配合装箱/拆箱判断:
object obj = 42;
if (obj is int) { /* true */ }
// var x = obj as int; // 编译错误若要安全获取值类型,只能用 is + 显式拆箱,或用泛型方法(如 Convert.ChangeType);注意拆箱必须类型完全一致,obj is int 成立不代表 (int)obj 一定成功(比如 obj 是 long 装箱的 42,is int 为 false,但有人误以为可以强转)。
真正容易被忽略的是:is 对值类型的判断本质是“是否为该类型装箱后的对象”,它不支持隐式转换检查(比如 long 到 int),这点和 as 的适用范围限制一起,让值类型的安全转换始终比引用类型更繁琐。







