C#文本游戏中静态Area对象列表运行时空引用异常排查
解决静态Area列表未正确填充导致的NullReferenceException问题
咱们直接定位问题根源:静态Area字段的初始化顺序导致循环引用中的对象为null。
看你的Areas静态类,opening字段先被声明初始化,当它的options列表引用second时,second还没完成初始化(静态字段是按代码声明顺序依次初始化的),所以opening.options里的second其实是null。当你从test区域加载opening后,点击按钮跳转时,实际上是在调用一个null对象的load()方法,这就触发了NullReferenceException。
修复方案1:用静态构造函数确保正确初始化顺序
静态构造函数会在类第一次被访问时执行,能让我们完全控制初始化顺序,避免循环引用的问题:
public static class Areas { public static Area opening; public static Area second; // 静态构造函数,保证两个Area都实例化后再建立互相引用 static Areas() { // 先创建opening,暂时不添加second到options opening = new Area() { name = "Opening", text = "This is the first area, just a test for now, but will be fully filled out at a later time", time = 0, options = new List<Area>() }; // 创建second,此时opening已经存在,可以直接引用 second = new Area() { name = "second", text = "this is the second area for stuffs and stuffs", time = 0, options = new List<Area>() { opening } }; // 现在second初始化完成,把它添加到opening的options里 opening.options.Add(second); } }
修复方案2:优化按钮点击逻辑,避免字符串解析的潜在问题
你当前通过按钮名称的字符串拆分获取索引,这种方式很脆弱(比如按钮名称意外包含其他"b"字符时就会出错)。更好的做法是把Area对象直接绑定到按钮的Tag属性:
private void loadOptions() { MainWindow.app.options.Children.Clear(); // 用foreach循环更简洁,避免索引操作 foreach (var area in options) { Button b = new Button(); b.Content = area.name; // 把目标Area对象存在Tag里 b.Tag = area; b.Click += optionClick; MainWindow.app.options.Children.Add(b); } } private void optionClick(object sender, RoutedEventArgs e) { Button clicked = (Button)sender; // 直接从Tag取出Area对象,不用解析字符串 Area targetArea = (Area)clicked.Tag; targetArea.load(); }
额外小优化
你的代码里用了options.Count(),这是Linq的扩展方法,对于List<T>来说,直接用options.Count属性效率更高——Count()会额外遍历一次集合,而Count是List的内置属性,直接返回存储的长度值。
按照上面的修改,静态Area之间的引用就都是有效的了,点击按钮跳转时不会再出现空引用异常,同时代码的健壮性也得到了提升。
内容的提问来源于stack exchange,提问作者Raxmo
相关产品推荐
相关产品推荐

