前排提示:提出一个可以让 [^1] 这中语法可以在.NET Framework运行时中使用的方法
众所都周知,.NET Framework
(以下简称 .NF)作为一个被微软官方确认不在继续发布新特性的运行时,它所对应的C#语言版本被(官方形式上)永久地停更在了 C# 7.3(对应着 .NF 4.8
,如果是更早版本的 .NF
,那么其语言版本可能更古早)。
但是,由于C#是语言,而.NF是实现该语言的运行时,如果某些语言特性能够在 .NF 的框架下实现,那么我们实际上还是能在 Visual Studio
等IDE上直接通过修改对应的 .csproj
文件,增加 <LangVersion>
,来使用新的语言特性的。
运行时与语言的关系就类似于……我用口头说话来指挥雇佣工干活,我说的话(
语言
)和他能干的活(运行时
)一般来说是没有一一对应的关系的。C#更高级的语言可以认为是我会更多的词汇,但是如果这个词汇所代表的特性能够被现有的运行时来实现,那么新版本的C#语言也是可以使用 .NF 来编译运行。
比如我比较喜欢的 Pattern Matching enhancements (C# 9.0),就能让我们在代码里使用 is not
的关键词。
if (e is not string {
Length: > 5} short_str)
{
// ... 如果e不满足“非空”且“长度大于5”的条件
}
这本质上是一些语法糖,所以 .NF
是支持这些语法的。
微软官方对于这些通过改 .csproj
文件就能实现的功能具体有哪些并没有写明的文档可以参考,有的只是运行时对应的“保证语言特性100%支持的版本”,它列在了下面的网页中。
https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/configure-language-version
C# 12 is supported only on .NET 8 and newer versions. C# 11 is supported only on .NET 7 and newer versions. C# 10 is supported only on .NET 6 and newer versions.
我们知道当然不是如此,某些C# 12的功能也能在 .NF
下使用,比如 Primary constructors(前提是更新 Visual Studio 2022
到版本 17.6 以上,总之更新到最新就对了)。
C#语言的新功能在新的运行时能力加持下,可能会带来执行速度的提升,但是在旧的运行时版本下,可能只是语法糖。
不过!就算是语法糖,那也能极大地提高代码可读性,减少出错,比如上面的 e is not string
,那就比 !(e is string)
更容易理解,因为后者再叠加上if
,就变成了
if (!(e is string))
布尔取反被夹在了俩括号之间,不小心就看错了,尤其是对新手而言。我认为一个好的高级语言一定是能够帮助程序员更加专注于业务逻辑而非语法本身的。所以,这种新特性虽然不能提高执行效率,但我仍然推荐大家使用。
下面我就稍微列一下我个人最喜欢的语言特性【排名部分先后】:
- 模式匹配 https://learn.microsoft.com/zh-cn/dotnet/csharp/fundamentals/functional/pattern-matching
- 主构造函数 https://learn.microsoft.com/zh-cn/dotnet/csharp/whats-new/tutorials/primary-constructors
- 全局using指令 https://learn.microsoft.com/zh-cn/dotnet/csharp/whats-new/csharp-10#global-using-directives
- 原始字符串文本 https://learn.microsoft.com/zh-cn/dotnet/csharp/whats-new/csharp-11#raw-string-literals
- 从末尾运算符 ^ 开始索引 https://learn.microsoft.com/zh-cn/dotnet/csharp/language-reference/operators/member-access-operators#index-from-end-operator-
俗话说,重要的事情留到最后,没错,今天的主角就是 5. 从末尾运算符 ^ 开始索引。
^
是个啥
相信很多读者必写过这样的代码:
var last = list[list.Count - 1];
噢!那丑陋的.Count - 1
。如果变量名再长点,再多点额外的业务逻辑:
var diff = some_sort_of_list