C#中值类型数组转IEnumerable<object>失败问题咨询
问题解答
1. 原代码失效的原因
- .NET 中泛型协变仅支持引用类型,值类型数组(如
short[]、double[])无法隐式转换为IEnumerable<object>。虽然单个值类型实例可以装箱为object,但值类型数组本身实现的是IEnumerable<[值类型]>(比如short[]实现IEnumerable<short>),而非IEnumerable<object>,因此tmpobj is IEnumerable<object>的判断会返回false。 - 判断失败后,代码会执行
tmpobj.ToString(),对于数组来说,这会返回数组的类型名称(如System.Int16[]),而非遍历元素写入集合,这就是异常行为的根源。
2. 代码修改方案
核心思路是改用**非泛型的IEnumerable**进行判断(所有数组和可枚举类型都实现了这个接口),同时排除字符串(避免把字符串拆成单个字符遍历)。修改后的代码如下:
ManagementObjectCollection searchResults = new ManagementObjectSearcher( "select * from " + key).Get(); // 测试用例:"Win32_ComputerSystem" int counter = 0; foreach (ManagementBaseObject? searchResult in searchResults) { if (searchResult is null) continue; counter += 1; foreach (PropertyData? property in searchResult.Properties) { if (property.Name is null) { continue; } object tmpobj = searchResult.GetPropertyValue(property.Name); string propertyname = $"{counter} | {property.Name}"; if (tmpobj is null) { continue; } // 先排除字符串,再判断是否为非泛型可枚举类型 if (tmpobj is not string && tmpobj is IEnumerable tmpcollection) { foreach (object item in tmpcollection) { descriptor.Properties.Add(propertyname, item?.ToString()); } } else { descriptor.Properties.Add(propertyname, tmpobj.ToString()); } } }
关键修改点:
- 替换
IEnumerable<object>为非泛型IEnumerable,覆盖所有可枚举类型(包括值类型数组)。 - 增加
tmpobj is not string判断,避免误将字符串当作可枚举集合遍历字符。 - 用
item?.ToString()简化空值处理,替代嵌套的空值检查逻辑。
内容的提问来源于stack exchange,提问作者Christof Lindner
相关产品推荐
相关产品推荐

