如何在独立Windows窗体引用RocketMain对象?空引用异常排查
问题解决与优化方案
一、修复NullReferenceException错误
错误核心原因是LaunchMenu类中声明的RocketMain RocketMain变量仅做了声明,未实例化,导致调用RocketMain.LaunchRocket时触发空引用异常。
1. 修正LaunchMenu窗体代码
在构造函数中初始化RocketMain实例,确保变量不为null:
public partial class LaunchMenu : Form { private RocketMain RocketMain; public LaunchMenu() { InitializeComponent(); // 实例化RocketMain对象 RocketMain = new RocketMain(); } // other code private void L1NextButton_Click(object sender, EventArgs e) { setVariables(); LaunchMenu2 launchMenu2 = new LaunchMenu2(); launchMenu2.Show(); this.Hide(); } public void setVariables() { string LaunchPlanet = Convert.ToString(PlanetSelection.SelectedValue); // 此时RocketMain已实例化,可正常调用方法 RocketMain.SetLaunchPlanet(LaunchPlanet); string DestPlanet = Convert.ToString(DestinationPlanetInput.SelectedValue); RocketMain.SetDestPlanet(DestPlanet); RocketMain.SetGravField(); } }
2. 重构RocketMain类
当前RocketMain类设计存在冗余:自身包含一个LaunchRocket实例,导致不必要的嵌套。重构为单一职责的实体类,直接操作自身属性:
internal class RocketMain { // 使用自动属性替代私有字段,更符合C#规范 public double LaunchPlanetGrav { get; private set; } public string LaunchPlanet { get; private set; } public string DestPlanet { get; private set; } public int RocketID { get; set; } public void SetLaunchPlanet(string planet) { LaunchPlanet = planet; } public void SetDestPlanet(string dPlanet) { DestPlanet = dPlanet; } public void SetGravField() { MessageBox.Show("it works"); switch (LaunchPlanet) { case "Earth": LaunchPlanetGrav = 9.8; break; case "Mars": LaunchPlanetGrav = 3.71; break; case "Venus": LaunchPlanetGrav = 8.87; break; case "Mercury": LaunchPlanetGrav = 3.70; break; case "Uranus": LaunchPlanetGrav = 8.87; break; case "Neptune": LaunchPlanetGrav = 11.15; break; case "ISS": LaunchPlanetGrav = 0.98; break; default: break; } } }
二、简便的跨窗体传参方法
针对WinForms新手,推荐两种直观易上手的传参方式:
1. 构造函数传参(最常用)
在LaunchMenu2中添加带参数的构造函数,直接传入RocketMain实例:
// LaunchMenu2窗体代码 public partial class LaunchMenu2 : Form { private RocketMain _rocketData; // 带参数的构造函数 public LaunchMenu2(RocketMain rocketData) { InitializeComponent(); _rocketData = rocketData; // 示例:在窗体中使用传入的数据 // lblLaunchPlanet.Text = $"发射行星:{_rocketData.LaunchPlanet}"; } }
修改LaunchMenu中的按钮点击事件调用:
private void L1NextButton_Click(object sender, EventArgs e) { setVariables(); // 传入已赋值的RocketMain实例 LaunchMenu2 launchMenu2 = new LaunchMenu2(RocketMain); launchMenu2.Show(); this.Hide(); }
2. 公共属性传参
在LaunchMenu2中定义公共属性,窗体显示前完成赋值:
// LaunchMenu2窗体代码 public partial class LaunchMenu2 : Form { public RocketMain RocketData { get; set; } public LaunchMenu2() { InitializeComponent(); } // 窗体加载时使用传入的数据 private void LaunchMenu2_Load(object sender, EventArgs e) { if (RocketData != null) { // lblDestPlanet.Text = $"目标行星:{RocketData.DestPlanet}"; } } }
调用时直接赋值公共属性:
private void L1NextButton_Click(object sender, EventArgs e) { setVariables(); LaunchMenu2 launchMenu2 = new LaunchMenu2(); launchMenu2.RocketData = RocketMain; launchMenu2.Show(); this.Hide(); }
内容的提问来源于stack exchange,提问作者owinius
相关产品推荐
相关产品推荐

