.NET 7隐式类型局部变量Nullable问题及简化解决方案问询
Nullable模式下var声明非可空引用类型的简写方案
问题回顾
在.NET 7中启用Nullable引用类型设置后,用var隐式声明的引用类型会被默认推断为可空类型,导致以下代码可以无警告地赋值null:
var nonEmpty = myList.Where(s => s.Length > 0).ToList(); nonEmpty = null; // 编译器未触发预期的警告/错误
显式声明类型(如List<string> nonEmpty = ...)可以让变量变为非可空,触发null赋值警告,但面对长类型名称时这种写法过于繁琐。你尝试的三种写法中,仅第三种可编译,但它是null抑制运算符而非真正的非可空声明:
// 以下两种写法均无法编译 var! nonEmpty = myList.Where(s => s.Length > 0).ToList(); var nonEmpty! = myList.Where(s => s.Length > 0).ToList(); // 仅此写法可编译,但属于null抑制,未改变变量可空性 var nonEmpty = myList.Where(s => s.Length > 0).ToList()!
当前可用的简写方案
1. 利用类型别名简化长类型声明
如果需要重复使用某一长类型,可以先通过using声明类型别名,再用别名显式声明变量:
// 声明别名 using StringList = System.Collections.Generic.List<string>; // 使用别名声明非可空变量 StringList nonEmpty = myList.Where(s => s.Length > 0).ToList(); nonEmpty = null; // 触发预期的Nullable警告
这种方式避免了重复书写完整的长类型名称,同时保证变量为非可空类型。
2. 借助模式匹配推断非可空类型
通过C#的var模式匹配,可以在局部作用域内让var推断出非可空引用类型:
if (myList.Where(s => s.Length > 0).ToList() is var nonEmpty) { // 此处nonEmpty的类型为List<string>(非可空) nonEmpty = null; // 编译器会触发Nullable警告 }
这种写法无需显式声明类型,且变量在匹配后的作用域内为非可空,但仅适用于能包裹在条件块中的场景。
3. 注意:!后缀的局限性
你尝试的第三种写法var nonEmpty = ...!是null抑制运算符,它的作用是告诉编译器“当前表达式不会为null”,但变量本身的类型仍然是可空的(List<string>?)。后续对该变量赋值null时,编译器不会触发警告,因此这并不是真正将变量声明为非可空的解决方案。
未来语言提案进展
目前C#语言团队正在讨论**var! 语法提案**,该提案旨在允许开发者通过var!直接声明隐式类型变量为非可空引用类型,替代显式类型声明。截至2024年,该提案仍处于设计评估阶段,尚未正式加入C#稳定版本,但已被纳入语言改进的候选方向。
内容的提问来源于stack exchange,提问作者Joe
相关产品推荐
相关产品推荐

