C#中如何永久修改类成员变量?方法内修改不生效求助
你遇到的问题根本原因不是ref关键字的用法,而是对象实例不共享导致的——你在MainConsole里创建了两个独立的MainGame实例(m和j),同时在MainGame的Main方法里还额外创建了MainConsole实例,这些都是完全独立的对象,它们的成员变量自然不会互相影响。
问题代码拆解
先看你的MainConsole代码:
public partial class MainConsole : Form { MainGame m = new MainGame(); MainGame j = new MainGame(); // 这个实例完全没用到,还浪费内存 private void ConsoleInput2_KeyDown(object sender, KeyEventArgs e) { if (e.KeyCode == Keys.Return) { Text_IP_Connected.Text = m.checkCommands(ConsoleInput2.Text); if (m.Is_Connected == 1) vic_sft.Enabled = true; else vic_sft.Enabled = false; } } }
这里的m是MainConsole类自己创建的MainGame实例,而你在MainGame的Main方法里又创建了另一个MainConsole:
static void Main(string[] args) { Application.EnableVisualStyles(); Application.Run(new MainConsole()); // 这是实际运行的窗体 MainConsole m = new MainConsole(); // 这是另一个完全独立的窗体实例,和上面的没关系 }
所以你在运行的窗体里修改的是m这个MainGame实例的变量,但如果其他地方用的是另一个MainGame实例,自然看不到变化——因为每个实例都有自己的Connected_IP和Is_Connected副本。
解决方案
根据你的需求,有两种常见的解决思路:
1. 使用静态成员变量(适合全局共享的状态)
如果你的Connected_IP和Is_Connected是全局唯一的状态(整个程序只需要一份),可以把它们改成静态成员:
class MainGame { // 改成static,所有MainGame实例共享这两个变量 public static string Connected_IP = " "; public static short Is_Connected = 0; static void Main(string[] args) { Application.EnableVisualStyles(); Application.Run(new MainConsole()); // 这里不需要再new MainConsole了,Application.Run已经启动了窗体 } // 方法也可以改成static,因为操作的是静态变量 public static ref string checkCommands(string command) { IP_DataBase ips = new IP_DataBase(); string[] dump; if (command.Contains("connect")) { dump = command.Split(' '); // 修复循环逻辑:先默认设为无效,找到匹配再修改 Connected_IP = "Invalid IP"; Is_Connected = 0; for (int i = 0; i < ips.IPS.Length; i++) { if (dump[1] == ips.IPS[i]) { Connected_IP = dump[1]; Is_Connected = 1; break; } } } else if (command.Contains("quit")) { Connected_IP = "Not Connected"; Is_Connected = 0; } return ref Connected_IP; } }
然后在MainConsole里直接调用静态方法,不需要创建MainGame实例:
public partial class MainConsole : Form { private void ConsoleInput2_KeyDown(object sender, KeyEventArgs e) { if (e.KeyCode == Keys.Return) { Text_IP_Connected.Text = MainGame.checkCommands(ConsoleInput2.Text); if (MainGame.Is_Connected == 1) vic_sft.Enabled = true; else vic_sft.Enabled = false; } } }
2. 共享同一个实例(适合需要多个实例的场景)
如果你以后可能需要多个MainGame实例,那应该让所有需要访问的地方共享同一个实例。比如在启动窗体的时候把实例传递进去:
class MainGame { public string Connected_IP = " "; public short Is_Connected = 0; static void Main(string[] args) { Application.EnableVisualStyles(); // 创建一个MainGame实例 MainGame gameInstance = new MainGame(); // 把实例传递给MainConsole Application.Run(new MainConsole(gameInstance)); } public ref string checkCommands(string command) { // 逻辑和之前一样,已修复循环问题 IP_DataBase ips = new IP_DataBase(); string[] dump; if (command.Contains("connect")) { dump = command.Split(' '); Connected_IP = "Invalid IP"; Is_Connected = 0; for (int i = 0; i < ips.IPS.Length; i++) { if (dump[1] == ips.IPS[i]) { Connected_IP = dump[1]; Is_Connected = 1; break; } } } else if (command.Contains("quit")) { Connected_IP = "Not Connected"; Is_Connected = 0; } return ref Connected_IP; } }
然后修改MainConsole的构造函数,接收传递过来的实例:
public partial class MainConsole : Form { private MainGame _gameInstance; // 自定义构造函数,接收MainGame实例 public MainConsole(MainGame gameInstance) { InitializeComponent(); _gameInstance = gameInstance; } private void ConsoleInput2_KeyDown(object sender, KeyEventArgs e) { if (e.KeyCode == Keys.Return) { Text_IP_Connected.Text = _gameInstance.checkCommands(ConsoleInput2.Text); if (_gameInstance.Is_Connected == 1) vic_sft.Enabled = true; else vic_sft.Enabled = false; } } }
额外提示:修复你的循环逻辑
原来的循环里,如果当前IP不匹配就立刻设置Connected_IP = "Invalid IP",这会导致如果前几个IP不匹配但最后一个匹配,最终结果还是Invalid IP——正确的逻辑应该是先默认设置为无效,只有找到匹配的IP才修改为有效。我在上面的代码里已经修正了这个问题。
内容的提问来源于stack exchange,提问作者ShAlooL

