C#自定义类数组报错问题求解及数组概念详解需求
错误原因与修复代码
你碰到的Object reference not set to an instance of an object空引用异常,核心问题出在引用类型数组的初始化逻辑:
执行new player[2]时,只是创建了一个能容纳2个player对象引用的数组容器,但数组里的每个元素默认都是null——相当于没有指向任何实际的player实例。直接访问b[0].name,本质是在一个不存在的对象上调用属性,自然会触发报错。
而string数组能正常运行,是因为字符串字面量(比如"Jordan")会被C#特殊处理,赋值时直接把现成的字符串实例引用存到数组元素里。
修复后的完整代码
static void Main(string[] args) { // 第一种string数组:正常运行 string[] a = new string[2]; a[0] = "Jordan"; a[1] = "Pippen"; Console.WriteLine(String.Join(",", a)); // 第二种player数组:修复后正常运行 player[] b = new player[2]; // 先为每个数组元素创建player实例 b[0] = new player(); b[0].name = "Jordan"; b[1] = new player(); b[1].name = "Pippen"; // 重写ToString后,才能正确输出name属性 Console.WriteLine(String.Join(",", b)); } class player { public string name; // 重写ToString方法,让数组输出时显示name值 public override string ToString() { return name; } }
数组核心概念详解
1. 数组的基本性质
数组是C#中固定大小的同类型元素集合,创建时必须指定长度,且长度一旦确定就无法修改。数组元素分为两类:值类型和引用类型,两者的初始化逻辑完全不同。
2. 值类型数组:直接分配内存
值类型(比如int、bool、自定义struct)的数组,创建时会直接为每个元素分配内存,并自动初始化默认值(int默认0,bool默认false),可以直接修改元素的值:
int[] scores = new int[3]; scores[0] = 90; // 直接赋值,无需额外实例化
3. 引用类型数组:仅创建容器,需手动实例化对象
引用类型(比如自定义类、string、接口)的数组,创建时只分配了存储"对象引用"的空间,每个元素默认是null。必须先通过new 类名()创建对象实例,把实例的引用赋值给数组元素,才能访问对象的属性或方法。
你的错误就是跳过了"创建player实例"这一步,直接去访问null对象的name属性。
4. string的特殊之处
string虽然是引用类型,但C#对字符串做了特殊优化:字符串字面量会被存入字符串常量池,赋值时直接把常量池中的引用交给数组元素。另外string是不可变类型,但这不影响数组赋值——本质上只是给数组元素换了一个新的字符串引用。
5. 简化初始化的写法
可以用数组初始化器一步完成数组创建和对象实例化,代码更简洁:
player[] b = new[] { new player { name = "Jordan" }, new player { name = "Pippen" } };
内容的提问来源于stack exchange,提问作者ilovewz520

