Understand why NullReferenceException was unhandled?
我是一个初学者,我正在用C语言编写一个简单的Windows窗体程序(对我来说不是那么容易,但对一个专业的程序员来说),它的工作原理是这样的:一个窗体(contactForm类)从用户那里获得输入(名字、姓氏、地址、电子邮件和电话号码),并通过属性将其存储到contact类中的变量中。contact类从其他三个类(地址、电子邮件和电话)调用属性和方法来存储和验证用户的输入。contact类还包含一个override-toString方法,该方法将包含用户输入的变量格式化为字符串。在这一点上,我尝试用contactForm调用这个toString方法,并在一个消息框中显示该字符串,它工作得很好。但后来我尝试用另一个类(customer)调用该方法,该类具有contact类的对象,这是一个灾难。编译器不断为contact类(m_contact)的对象(表示为空)重新发出nullreferenceexception。代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 | public class Customer { private Contact m_contact; private int m_ID; public Customer() { }public Customer(Contact contactIn) { }public Customer(Contact contactIn, int id) { if (m_contact != null) { m_contact = new Contact(); m_contact = contactIn; } m_ID = id; }public Contact ContactData { get { return m_contact; } set { if (value != null) m_contact = value; } }public int ID { get { return m_ID; } set { m_ID = value; } } public override string ToString() { string strOut = string.Empty; **if ((!string.IsNullOrEmpty(m_contact.ToString())) && (m_contact != null) && (m_contact.Validate()))** { strOut = m_contact.ToString(); } else strOut = null; return strOut; } } |
}星号中的行是发现错误的行。这是m_contact.validate方法:
1 2 3 4 5 6 7 8 9 | public bool Validate() { bool ok = false; if (!string.IsNullOrEmpty(m_firstName) && (!string.IsNullOrEmpty(m_lastName)) && m_address.CheckData() && m_email.CheckEmail() && m_phone.CheckPhone()) ok = true; else ok = false; return ok; } |
为了更清晰起见,这是email.checkemail方法,但上述检查方法绝对不是问题:
1 2 3 4 5 6 7 8 9 | public bool CheckEmail() { bool ok = false; if ((!string.IsNullOrEmpty(m_personal)) || (!string.IsNullOrEmpty(m_work))) ok = true; else ok = false; return ok; } |
这是来自contactForm类的代码,显示了contact类的toString方法,完全没有问题:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 | public partial class ContactForm : Form { private Contact m_contact; private bool m_closeForm; public ContactForm(string title) { InitializeComponent(); m_contact = new Contact(); this.Text = title; InitializeGUI(); }public Contact ContactData { get { return m_contact; } set { if (value != null) m_contact = value; } }private void InitializeGUI() { txtFirstName.Text = string.Empty; txtLastName.Text = string.Empty; txtHomePhone.Text = string.Empty; txtCellPhone.Text = string.Empty; txtEMailBus.Text = string.Empty; txtEMailPr.Text = string.Empty; txtStreet.Text = string.Empty; txtCity.Text = string.Empty; txtZip.Text = string.Empty; FillCountryComboBox(); cmbCountry.SelectedIndex = (int)Countries.Sverige; m_closeForm = true; }private void FillCountryComboBox() { cmbCountry.Items.AddRange(Enum.GetNames(typeof(Countries))); } private void MainForm_FormClosing(object sender, FormClosingEventArgs e) { if (m_closeForm) e.Cancel = false; else e.Cancel = true; }public bool ReadInput() { m_contact.FirstName = txtFirstName.Text; m_contact.LastName = txtLastName.Text; m_contact.AddressData = ReadAddress(); m_contact.EmailData = ReadEmail(); m_contact.PhoneData = ReadPhone(); bool ok = m_contact.Validate(); if (ok) { return true; } else { MessageBox.Show("Please provide at least your firstname, lastname, phone number, email address, city and country"); return false; } }private Address ReadAddress() { Address m_address = new Address(); m_address.Street = txtStreet.Text; m_address.City = txtCity.Text; m_address.ZipCode = txtZip.Text; m_address.Country = (Countries)cmbCountry.SelectedIndex; return m_address; }private Email ReadEmail() { Email m_email = new Email(); m_email.Work = txtEMailBus.Text; m_email.Personal = txtEMailPr.Text; return m_email; }private Phone ReadPhone() { Phone m_phone = new Phone(); m_phone.Home = txtHomePhone.Text; m_phone.Other = txtCellPhone.Text; return m_phone; } private void btnOK_Click(object sender, EventArgs e) { if (ReadInput()) { UpdateGUI(); m_closeForm = true; this.Close(); } else m_closeForm = false; }public void UpdateGUI() { string strOut = m_contact.ToString(); MessageBox.Show(strOut); } } } |
}此外,主窗体调用customer-toString方法以在消息框上显示消息。这是主窗体中的方法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | private void btnAdd_Click(object sender, EventArgs e) { ContactForm contForm = new ContactForm("Add a new customer"); Customer cust = new Customer(); int index = lstResults.SelectedIndex; if (index != -1) contForm.ContactData = customerMngr.GetCustomer(index).ContactData; if (contForm.ShowDialog() == DialogResult.OK) { lstResults.Items.Clear(); if (contForm.ReadInput() && (!String.IsNullOrEmpty(cust.ToString()) && (cust != null))) { MessageBox.Show(cust.ToString()); } } |
为什么客户类中的m_联系人为空,而不是contactForm类中的联系人?抱歉,这篇文章篇幅太长了,我真的很难理解。谢谢您!
首先,必须检查,如果
基本上,重写
1 2 3 4 5 6 | **if ((!string.IsNullOrEmpty(m_contact.ToString())) && (m_contact != null) && (m_contact.Validate()))** { strOut = m_contact.ToString(); } else strOut = null; |
到:
1 2 3 4 5 6 | if (m_contact != null && !string.IsNullOrEmpty(m_contact.ToString()) && m_contact.Validate()) { strOut = m_contact.ToString(); } else strOut = null; |