关键在于通过Type对象调用Array.CreateInstance创建数组:先用GetElementType或Type.GetType获取元素类型,再传入长度生成Array实例,赋值须用SetValue/GetValue,不可强制转型。

直接用反射创建未知类型的数组,关键不是“造出数组”,而是准确获取元素类型、确定长度、再调用 Array.CreateInstance —— 它不依赖泛型约束,也不需要提前知道是 string[] 还是 MyClass[],只要拿到 Type 对象就能生成。
从变量或类型信息中提取元素类型
如果已有某个数组变量(比如 object arr = new int[5];),先用 arr.GetType().GetElementType() 拿到元素类型;如果是纯类型描述(如通过字符串解析或配置传入的 "System.DateTime"),就用 Type.GetType() 解析。注意:若类型在非默认程序集(如自定义类库),需确保已加载且传入完整命名空间+程序集名称。
-
常见坑:
typeof(int[]).GetElementType()返回Int32,但typeof(List<int>).GetElementType()</int>返回null—— 只有数组、指针、引用类型才支持该方法 - 安全写法:检查
type.IsArray为true后再调用GetElementType()
动态确定数组长度并创建实例
长度可以来自配置、用户输入或运行时计算。调用 Array.CreateInstance(elementType, length) 即可生成一维数组;若需多维,用重载版本如 Array.CreateInstance(elementType, 3, 4, 2)。返回值是基类 Array,后续赋值或读取需用 SetValue/GetValue 方法,避免强制转型失败。
- 例如:
var arr = Array.CreateInstance(typeof(string), 3); arr.SetValue("hello", 0); - 不能写
(string[])arr—— 因为arr是Array类型,不是string[]的具体实例,C# 不允许这种向下转型
对动态数组进行安全赋值与类型校验
使用 SetValue 时,.NET 会自动做类型检查:若传入 DateTime 到 string[] 中,会抛出 ArgumentException。可在赋值前用 elementType.IsAssignableFrom(value.GetType()) 预判兼容性(尤其处理继承体系时,如往 Animal[] 里塞 Dog 实例)。
- 批量初始化可用
Array.Copy或循环 +SetValue,不推荐用foreach遍历Array后直接赋值(只读) - 若需 LINQ 操作,可转成
IEnumerable:arr.Cast<object>()</object>,但注意这会装箱值类型,且丢失原始类型信息
结合泛型工具类封装复用逻辑
把上述步骤收拢成一个静态方法,比如 ArrayHelper.Create<t>(int length)</t> 用于已知泛型场景;更通用的是 ArrayHelper.Create(Type elementType, int length),内部统一走反射创建。这样上层代码只需传入类型和长度,不用重复写 GetElementType 和 CreateInstance。
- 示例封装要点:校验
elementType是否为有效运行时类型、长度是否 ≥ 0、是否支持默认构造(对引用类型无影响,但值类型数组元素会自动初始化为default(T)) - 避免缓存
Type对象引发内存泄漏——除非明确类型集合固定且数量极少

















