如何在类初始化时将数组赋值给只读HashSet属性?
解决方法与语法说明
嘿,这个场景我之前也碰到过,其实核心是利用C#里的集合初始化器语法,结合几种写法就能搞定你的需求,下面分两部分说:
一、实现方法
你有几种可选的方式,根据你的场景灵活选择:
1. 直接在对象初始化器中展开数组元素
如果你的数组元素数量固定或者可以逐个引用,直接把数组元素放到集合初始化器的大括号里就行:
var someStringArray = new [] { "someValue1", "someValue2"}; var myClassInstance = new SomeClass { SomeReadonlyPropertyHashSetOfStrings = { someStringArray[0], someStringArray[1] } };
编译器会自动把大括号里的每个元素转换成对HashSet.Add()的调用——因为你的属性已经有默认初始化的HashSet实例,所以哪怕setter是private也能正常工作。
2. 批量添加(适合长度不固定的数组)
如果数组长度不确定,逐个写元素太麻烦,推荐给SomeClass加一个接收IEnumerable<string>的构造函数,在构造函数里批量处理:
class SomeClass { public HashSet<string> SomeReadonlyPropertyHashSetOfStrings {get; private set; } = new HashSet<string>(); // 新增构造函数 public SomeClass(IEnumerable<string> initialStrings) { // 使用UnionWith批量添加,自动去重(符合HashSet特性) SomeReadonlyPropertyHashSetOfStrings.UnionWith(initialStrings); } } // 初始化时直接传入数组 var myClassInstance = new SomeClass(someStringArray);
3. 初始化后批量添加
如果不想修改原类的定义,也可以在对象初始化完成后,直接调用集合的方法添加:
var myClassInstance = new SomeClass(); myClassInstance.SomeReadonlyPropertyHashSetOfStrings.UnionWith(someStringArray);
这种方式最简单,缺点是不能在一行的对象初始化器里完成,但胜在不需要改动原类代码。
二、语法的官方说明
你用到的这种{ ... }写法属于C#的集合初始化器,是对象初始化器的扩展特性:
- 当你对一个实现了
IEnumerable且包含Add方法的属性使用{ 元素1, 元素2... }时,编译器会自动生成调用该集合Add方法的代码。 - 哪怕属性的setter是
private,只要getter能返回一个已初始化的集合实例(像你代码里那样给属性赋了默认值new HashSet<string>()),这个语法就能正常工作——因为它并没有给属性重新赋值(这就是直接用=无效的原因),而是对getter返回的现有集合实例调用Add方法。
这个特性的官方说明在C#语言规范的"Collection initializers"章节中,你可以通过微软官方的C#文档渠道找到详细内容。
内容的提问来源于stack exchange,提问作者James Hancock
相关产品推荐
相关产品推荐

