C#中是否可重写或创建字面量、复用数组字面量语法?
C# 没有提供完全自定义全新字面量、重写内置字面量解析规则的能力,所有内置字面量(数字、字符串、数组大括号初始化语法等)的解析逻辑都是编译器硬编码实现的。你目前用到的运算符重载、隐式类型转换运算符,都是编译器预留的有限扩展点,本质是类型转换/运算符行为的自定义,不是字面量本身的自定义。
针对你想要的复用类数组大括号语法初始化自定义DynamicList<T>类型的需求,分版本有不同的实现方案,但是无法完全做到你写的DynamicList<int> list = {0,1,2};这种完全不带new、和数组初始化完全一致的写法,具体可实现的效果如下:
C# 12 以前版本:集合初始化器语法
只要你的自定义集合类型满足两个条件,就可以用
new 类型() {元素1,元素2}的写法初始化:- 实现
IEnumerable接口(哪怕是显式接口实现也可以,编译器仅要求类型存在该接口实现,不会实际调用GetEnumerator做初始化) - 提供和传入元素签名匹配的
Add方法,比如针对单元素集合添加public void Add(T item)即可。
示例代码:
class DynamicList<T> : DynamicCollection, IEnumerable { // 原有业务代码 public void Add(T item) { // 实现单元素添加逻辑 } IEnumerator IEnumerable.GetEnumerator() { // 初始化流程不会调用该方法,实际使用时返回集合对应的枚举器即可 throw new NotImplementedException(); } } // 初始化写法 DynamicList<int> list = new DynamicList<int> {0,1,2};编译器会自动把上述代码翻译为:先调用
DynamicList<int>的无参构造函数创建实例,再依次调用Add方法传入0、1、2三个元素。如果你不想写new + 构造函数,也可以加一个从数组到自定义类型的隐式转换运算符:
class DynamicList<T> : DynamicCollection { // 原有业务代码 public static implicit operator DynamicList<T>(T[] items) { var list = new DynamicList<T>(); foreach(var item in items) list.Add(item); return list; } } // 可以简化成如下写法,但是必须带new[]声明数组 DynamicList<int> list = new[] {0,1,2};- 实现
C# 12 及以上版本:集合表达式
C# 12 新增了集合表达式语法,只要给你的自定义类型标记
[CollectionBuilder]特性,指定对应的构建器方法,就可以用更简洁的方括号语法直接初始化,效果和你要的数组字面量初始化几乎一致:// 标记集合构建器 [CollectionBuilder(typeof(DynamicListBuilder), "Create")] class DynamicList<T> : DynamicCollection { // 原有业务代码 } // 定义构建器类 internal static class DynamicListBuilder { public static DynamicList<T> Create<T>(ReadOnlySpan<T> items) { var list = new DynamicList<T>(); foreach(var item in items) list.Add(item); return list; } } // 直接用集合表达式初始化,不需要写new DynamicList<int> list = [0,1,2];这是目前C#里最接近自定义集合字面量的官方实现,支持所有集合类型,包括列表、字典、不可变集合等。
另外补充说明你提到的正则类隐式转换的方案:这种方式本质是利用编译器对已存在字面量(比如字符串字面量)的隐式转换规则模拟字面量效果,并不是真的自定义了正则专用的字面量语法,你无法通过这种方式创造C#不存在的字面量格式。
内容的提问来源于stack exchange,提问作者user14459251

