C# 扩展方法只会写 this 吗?C# 14 新语法直接把扩展方法玩出了花
.NET 10 的扩展方法语法糖?哦,用 `extension` 块定义扩展,支持属性和方法了,以前不行,现在行,真稀奇。静态扩展成员?太晚了点,给 `DateTime` 添加静态方法,终于能优雅了。升级吧,不然怎么享受这些新玩具?
目录7 个章节
前言
PS: 不是,AI编程都普及了,怎么还有人研究编程语言的语法?
开个玩笑哈哈,一些简单和定制性比较强的代码还是手写比较好,有和AI对话的时间,我都把代码写好了😄
最近我在给 StarBlog 写一些分析脚本,需要用到扩展方法来简化代码,我想到前段时间看到 .NET10 的更新文档说有新的扩展方法语法,我本来以为是和 Kotlin 一样不再需要写一个静态类了,结果还是要…
不过新的写法还挺好用的。
PS: 虽然代码是自己写的,但文档不用自己看了,直接让AI总结😄
正好借本文记录一下这个新的写法。
从静态方法到扩展块
传统的扩展方法需要每个方法都重复写 this 参数,且只能扩展方法。新语法通过 extension 关键字定义一个块,将目标类型集中声明。
传统写法是这样的
public static class StringExtensions {
// 每个方法都要写一遍 (this string str)
public static bool IsValidEmail(this string str) => str.Contains("@");
public static string ToTitleCase(this string str) => ...;
}
新语法(C# 14 / .NET 10)
public static class MyExtensions {
// 定义一个针对 string 的扩展块,str 是接收者名称
extension(string str) {
// 1. 扩展属性 (以前做不到)
public bool IsValidEmail => str.Contains("@");
// 2. 扩展方法 (不再需要写 static 和 this)
public string ToTitleCase() => char.ToUpper(str[0]) + str.Substring(1);
}
}
新语法支持的成员类型
这是 .NET 10 最强大的地方,扩展的能力范围极大地拓宽了:
| 成员类型 | 是否支持 | 示例语法 |
|---|---|---|
| 实例方法 | 是 | public void M() => ... |
| 实例属性 | 是 | public int Length => str.Length; |
| 静态方法 | 是 | public static void Help() => ... |
| 静态属性 | 是 | public static string Default => "None"; |
| 运算符重载 | 是 | public static bool operator +(string a, MyType b) |
| 索引器 | 是 | public char this[int i] => str[i]; |
静态扩展成员
以前我们无法给一个现有的类(比如 DateTime 或 int)添加静态工具方法,现在可以了。
public static class DateTimeExtensions {
// 注意:括号内只有类型,没有实例名称,表示静态扩展
extension(DateTime) {
public static DateTime Tomorrow => DateTime.Now.AddDays(1);
}
}
// 使用时:
var nextDay = DateTime.Tomorrow; // 就像 DateTime 原生自带的一样
泛型支持
新语法对泛型的支持非常优雅,尤其是在处理集合(LINQ 风格)时:
public static class EnumerableExtensions {
extension<T>(IEnumerable<T> source) {
// 扩展属性:判断集合是否为空
public bool IsEmpty => !source.Any();
// 扩展方法
public void ForEach(Action<T> action) {
foreach (var item in source) action(item);
}
}
}
实际代码
既然说到是给 StarBlog 写的脚本,那我也把实际用到的代码放出来吧 (水字数(bushi)
实际上是一个提取 markdown 二级标题下段落的扩展方法
public static class MyExtensions {
extension(Post post) {
public string GetSection(string title) {
return ExtractSectionRegex(post.Content, title);
}
public Dictionary<string, string> GetSections(params string[] titles) {
var dict = new Dictionary<string, string>();
foreach (var title in titles) {
dict.Add(title, post.GetSection(title));
}
return dict;
}
}
private static string ExtractSectionRegex(string content, string title) {
// 匹配目标标题开始,直到下一个标题或文档末尾
string pattern = $@"##\s*{title}\s*([\s\S]*?)(?=\n##|$)";
var match = Regex.Match(content, pattern);
return match.Success ? match.Groups[1].Value.Trim() : string.Empty;
}
}
实际上这个 GetSections 方法又可以用 LINQ 语法简化一下
public Dictionary<string, string> GetSections(params string[] titles) {
return titles.ToDictionary(title => title, title => post.GetSection(title));
}
再用 method group 简化一下,最终效果
public Dictionary<string, string> GetSections(params string[] titles) {
return titles.ToDictionary(title => title, post.GetSection);
}
翻译翻译,什么叫优雅?!🐸
小结
新的扩展语法糖还是很甜的,在我看来有几个优势:
- 代码更自然:扩展属性让 API 看起来更像目标类型的原生一部分,而不是非要调用一个带括号的方法。
- 逻辑集中:在一个
extension块里定义所有相关的扩展,代码结构比散落在静态类里的方法更清晰。 - 零破坏性:新语法与旧的
this扩展方法语法完全兼容,可以根据喜好混合使用。
注意: 只有安装了 .NET 10 SDK 并在项目文件中将 <LangVersion> 设置为 14.0 或 preview,才能使用这些新特性。
所以赶紧把项目都升级到 .NET10 把😄
PS: 我这个 StarBlog 项目一路从 .NET6 升级到 .NET10,也算是有点历史的项目了🤣
_EOF_
C# 扩展方法只会写 this 吗?C# 14 新语法直接把扩展方法玩出了花
- 本文作者:
- 程序设计实验室
- 版权声明:
- 本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
相关文章
C#中AES加密的实现
AES算法简介 高级加密标准(英语:Advanced Encryption Standard,缩写:AES),在密码学中又称Rijndael加密法,是美国联邦政府采用的一种区块加密标准。这个标准用来替代原先的DES,已经被多方分析且广为全世界所使用。经过五年的甄选流程,高级加密标准由美国国家标准与技术研究院(NIST)于2001年11月26日发布于FIPS PUB 197,并在2002年5月26日
2022-05-27 · C# · 约 1 分钟
让 C# 也拥有 gofmt 般的体验:用 CSharpier + Roslyn 实现 csfmt
C# 代码长到像答辩?用 CSharpier 自动折行,再用 Roslyn 修正 K&R 花括号,Taskfile 一键收尾。再补上 format-check,省得 CI 反复制造 Git diff。两步流水线并非原生 gofmt,顺序和版本仍得老实锁住。
2026-10-22 · C# · 约 1 分钟
一次小而美的重构:使用 C# 在 Avalonia 中生成真正好看的词云
重构StarBlogPublisher中词云展示功能的过程。作者对比了两个流行的C#词云库,最终选择了功能更强大的Sdcb.WordCloud。文章详细说明了如何使用该库获取词频数据并生成词云图像,并展示了重构前后的效果对比。
2025-04-26 · C# · 约 1 分钟
C#高性能数组拷贝实验
前言 昨天 wc(Wyu_Cnk) 提了个问题 C# 里多维数组拷贝有没有什么比较优雅的写法? 这不是问对人了吗?正好我最近在搞图像处理,要和内存打交道,我一下就想到了在C#里面直接像C/C++一样做内存拷贝。 优雅?no,要的就是装逼,而且性能还要强🕶 概念 首先澄清一下 C# 里的多维数组 (Multi-dimensional Array) 是这样的 byte[,] arr = new by
2023-01-30 · C# · 约 1 分钟
讨论
共 0 条加载评论中…