如何在初始化含null的数组时节省空间?及LINQ读取XML初始化数组问题
先给你捋清楚:如果是引用类型数组(比如string[]这种),直接用new string[N]初始化的时候,数组里所有元素默认就是null,这已经是最省空间的方式了——因为引用类型数组存的是对象引用,null就是空引用,不会额外占用对象的存储空间,只是占一个引用位(64位系统是8字节,32位是4字节)。
要是你用的是可空值类型数组(比如int?[]),同样new int?[N]默认元素全是null(也就是Nullable<T>的默认值),也没多余开销。
如果你的场景是数组里大部分元素都是null,想进一步优化的话,可以考虑用稀疏数组或者List<T>动态添加非null的元素,但如果必须用数组的话,默认初始化就是最优解了,毕竟数组是连续内存块,本身的存储开销已经最小。
先看你给的XML结构:
FIRST THIRD
这里有个关键错误:productA、productB、productC是XML元素,不是属性!你代码里用el.Attribute("productA")是拿不到值的,得用el.Element("productA")才行,不然会拿到null,直接取Value还会抛出空引用异常。
另外,productB被注释了,所以Element("productB")会返回null,这时候不能直接取Value,得做安全处理。给你修正后的代码:
// 假设keyValueList是你的XElement或XDocument根节点 string[] aaa = (from el in keyValueList.Elements("bbb") where (string)el.Attribute("ccc") == "12345" select new string[] { el.Element("productA")?.Value, // 安全访问,元素不存在就返回null el.Element("productB")?.Value, // 被注释的元素会返回null el.Element("productC")?.Value }).FirstOrDefault() ?? Array.Empty<string>();
给你解释下细节:
- 用
el.Element("productX")获取对应的XML元素,替换掉错误的Attribute方法 - 用
?.Value做安全访问,要是元素不存在(比如被注释的productB),不会抛出异常,直接返回null - 最后用
FirstOrDefault()拿到第一个匹配的<bbb>元素对应的数组,如果没有匹配的,返回空数组避免拿到null
要是你想后续维护更方便,也可以把要提取的产品名放到一个列表里,动态生成数组:
var productNames = new[] { "productA", "productB", "productC" }; string[] aaa = (from el in keyValueList.Elements("bbb") where (string)el.Attribute("ccc") == "12345" select productNames.Select(name => el.Element(name)?.Value).ToArray()) .FirstOrDefault() ?? Array.Empty<string>();
这样以后要加新的产品元素,只需要修改productNames数组就行,不用动LINQ查询的逻辑。
内容的提问来源于stack exchange,提问作者user1012506

