在 C# 12 中有“集合初始化可以简化”分析器IDE0028。
我一直想知道修复程序如何决定何时修复或不修复初始化程序,例如,,,,,等new()
。它的修复方法是用 替换合格的初始化程序。new List<string>()
new Collection<int>()
Array.Empty<double>()
new string[] { }
[]
例如:
// Collection initialization can be simplified
public List<string> Foo1 { get; } = new List<string>();
public HashSet<string> Foo2 { get; } = new HashSet<string>();
public ICollection<string> Foo3 { get; } = new List<string>();
public Dictionary<int, string> Foo4 = new Dictionary<int, string>();
// Collection initialization can be simplified (may change semantics)
public IEnumerable<string> Bar1 { get; } = new List<string>();
public ICollection<string> Bar2 { get; } = new Collection<string>();
// no code fix offered
public IDictionary<int, string> Baz1 = new Dictionary<int, string>();
我通常会选择适合特定用途的集合类型。因此,我不想盲目接受分析器的建议,而不了解编译器在看到时实际上会使用哪种集合类型[]
。
所以:
- 分析器/修复器如何决定何时建议修复,以及“可能改变语义”到底是什么意思
- 当编译器/运行时遇到
[]
“可能会改变语义”只是意味着在这里使用集合文字不会产生与您当前拥有的代码等效的代码。
确定使用哪种类型的规则在功能规范的构造和集合文字翻译部分中指定。
对于具体的类和结构(没有创建方法),集合文字将使用其无参数构造函数创建该类/结构的实例,然后添加元素。
如何将事物添加到集合中也遵循一些规则,但它们与此无关,因为任何集合文字中都没有元素。如果您感兴趣,请阅读规范。
这解释了为什么
Foo1
、Foo2
和Foo4
的情况不会改变语义。IEnumerable<T>
对于接口,规范提供了相对更多的自由。对于像或 这样的只读接口IReadOnlyList<T>
,编译器可以自由使用满足某些要求的任何具体类型。因此,该
Bar1
案例表示“可能会改变语义”。集合文字实际上是在Array.Empty()
后台翻译的。对于像这样的可变接口
ICollection<T>
,指定集合文字将始终为List<T>
,因此该Foo3
案例并没有说“可能会改变语义”,但Bar2
确实如此。最后,集合字面量根本不支持,
IDictionary<K, V>
因此没有 的诊断Baz1
。在所有接口中,集合字面量仅适用于IEnumerable<T>
、IReadOnlyCollection<T>
、IReadOnlyList<T>
和。ICollection<T>
IList<T>