为何C#存储声明和类型模式结果会触发CS0165未赋值变量错误?
C#模式匹配中未赋值变量报错及简洁写法问题
问题描述
我好奇为何以下两段代码都会触发错误CS0165: 使用未赋值的局部变量'i':
// Attempt #1 object obj = 4; bool isInt = obj is int i; if (isInt) Console.WriteLine("obj = {0}", i); // CS0165 // Attempt #2 object obj = 4; bool isInt; if (isInt = obj is int i) Console.WriteLine("obj = {0}", i); // CS0165
以下代码可以编译,但似乎没必要这么写:
object obj = 4; bool isInt = false; if (obj is int i) { isInt = true; Console.WriteLine("obj = {0}", i); }
在使用C#声明和类型模式时,有没有更简洁的方式存储测试条件的结果?
问题解答
报错原因
你遇到的CS0165错误,核心在于C#编译器的流分析规则:它不会跟踪普通布尔变量(比如isInt)和模式匹配变量(比如i)之间的依赖关系。
- 对于Attempt #1:你把
obj is int i的结果存入isInt后再判断分支,但编译器不会将“isInt为true”和“i已赋值”这两个逻辑关联起来。它只认可直接将obj is int i写在if条件中的场景——只有这时编译器能100%确定进入分支时i已完成赋值。 - Attempt #2同理:即便你把模式匹配结果赋值给
isInt后再做判断,编译器依然不会通过isInt的布尔值推断i的赋值状态,因此仍会报错。
简洁解决方案
如果既要保存类型检查的结果,又要合法使用模式变量i,推荐两种简洁且合规的写法:
方案一:分支内赋值结果(直观清晰)
这是最符合代码可读性要求的写法,逻辑明确,编译器完全认可:
object obj = 4; bool isInt = false; if (obj is int i) { isInt = true; Console.WriteLine("obj = {0}", i); } // 后续可正常使用isInt变量
这种写法并不冗余——毕竟你需要同时实现“保存检查结果”和“使用匹配后变量”两个需求,这是最直接的实现方式。
方案二:紧凑式赋值+判断(代码更短)
如果追求代码紧凑,可以借助逻辑运算符让编译器认可i的赋值状态:
object obj = 4; bool isInt; if ((isInt = obj is int i) && i is int) { Console.WriteLine("obj = {0}", i); }
这里的i is int是冗余的类型检查,但它能触发编译器的流分析,确认进入分支时i已赋值,同时完成isInt的赋值。不过这种写法可读性稍弱,不如方案一直观。
另外补充:如果后续不需要使用isInt变量,直接写if (obj is int i)并在分支内使用i即可,这是最简洁的模式匹配写法。
内容的提问来源于stack exchange,提问作者Jeff G
相关产品推荐
相关产品推荐

