结构体数组中嵌套数组访问引发NullReferenceException问题求助
解决C# struct数组中引用类型成员的NullReferenceException问题
问题代码
public struct player { public int[] PlayerHistory; public Boolean Absent; public player(Boolean b) { PlayerHistory = new int[20]; Absent = b; } static void Main(string[] args) { player[] Player = new player[10]; player[0].Absent = true; Player[0].PlayerHistory[0] = -1; } }
问题原因
player是值类型struct,创建player[] Player = new player[10];时,数组内每个元素会被默认初始化:值类型成员Absent设为默认值false,引用类型成员PlayerHistory设为null。- 修改
player[0].Absent = true;看似正常,本质是C#做了隐式值拷贝:先把数组索引0的player实例复制到临时变量,修改临时变量的Absent后再赋值回数组,但这个过程并没有初始化PlayerHistory,它依然是null。 - 访问
Player[0].PlayerHistory[0]时,因PlayerHistory为null,直接触发NullReferenceException。
解决方案
方案1:显式调用struct构造函数初始化数组元素
用自定义构造函数初始化数组目标元素,确保PlayerHistory被正确实例化:
player[] Player = new player[10]; // 用构造函数初始化索引0的player实例 Player[0] = new player(false); Player[0].Absent = true; Player[0].PlayerHistory[0] = -1;
方案2:将struct改为class(推荐,如果业务允许)
如果player不需要值类型特性(如值语义、栈分配等),改成引用类型class更符合常规逻辑:
public class player { public int[] PlayerHistory; public Boolean Absent; public player(Boolean b) { PlayerHistory = new int[20]; Absent = b; } static void Main(string[] args) { player[] Player = new player[10]; // 必须显式实例化class对象 Player[0] = new player(true); Player[0].PlayerHistory[0] = -1; } }
注意:class数组初始化时所有元素默认是null,必须显式new实例后才能访问成员。
方案3:检查并延迟初始化引用类型成员(不推荐)
如果必须保留struct,可在访问PlayerHistory前检查是否为null,通过值拷贝完成初始化:
player[] Player = new player[10]; Player[0].Absent = true; if (Player[0].PlayerHistory == null) { var temp = Player[0]; temp.PlayerHistory = new int[20]; Player[0] = temp; } Player[0].PlayerHistory[0] = -1;
这种方式需要处理值类型拷贝逻辑,代码繁琐,仅适合特殊场景。
总结
核心问题是值类型struct的默认初始化不会调用自定义构造函数,导致引用类型成员为null。优先选择方案1或方案2解决,代码更简洁易维护。
内容的提问来源于stack exchange,提问作者Thomas Weston
相关产品推荐
相关产品推荐

