1

我目前正在尝试返回一个数组,其中包含有关剧院座位的信息,例如座位号、名称、价格和状态。我正在使用一个组合框,我想根据选择列出所有空缺或保留的座位。当我在组合框中选择预留座位时,我调用了一个使用 AddRange 的方法。此方法应该循环遍历包含所有座位及其信息的数组。如果有空位,我将其添加到数组中。完成后,我返回这个数组。但是,我正在处理 ArgumentNullException。

主窗体:

namespace Assignment4
{
   public partial class MainForm : Form
   {
      // private const int totNumberOfSeats = 240;
      private SeatManager seatMngr; 
      private const int columns = 10;
      private const int rows = 10;

      public enum DisplayOptions
      {
         AllSeats,
         VacantSeats,
         ReservedSeats
      }

      public MainForm()
      {
         InitializeComponent();

         seatMngr = new SeatManager(rows, columns);
         InitializeGUI();
      }

      /// <summary>
      /// Fill the listbox with information from the beginning, 
      /// let the user be able to choose from vacant seats.
      /// </summary>
      private void InitializeGUI()
      {
         rbReserve.Checked = true;
         txtName.Text = string.Empty;
         txtPrice.Text = string.Empty;

         lblTotalSeats.Text = seatMngr.GetNumOfSeats().ToString();

         cmbOptions.Items.AddRange(Enum.GetNames(typeof(DisplayOptions)));
         cmbOptions.SelectedIndex = 0;

         UpdateGUI();
      }

      /// <summary>
      /// call on methods ValidateName and ValidatePrice with arguments
      /// </summary>
      /// <param name="name"></param>
      /// <param name="price"></param>
      /// <returns></returns>
      private bool ValidateInput(out string name, out double price)
      {
         bool nameOK = ValidateName(out name);
         bool priceOK = ValidatePrice(out price);

         return nameOK && priceOK;
      }

      /// <summary>
      /// Validate name using inputUtility, show error if input is invalid
      /// </summary>
      /// <param name="name"></param>
      /// <returns></returns>
      private bool ValidateName(out string name)
      {
         name = txtName.Text.Trim();

         if (!InputUtility.ValidateString(name))
         {
            //inform user
            MessageBox.Show("Input of name is Invalid. It can not be empty, " +   Environment.NewLine + "and must have at least one character.", " Error!");

            txtName.Focus();
            txtName.Text = " ";
            txtName.SelectAll();
            return false;
         }
         return true;
      }

      /// <summary>
      /// Validate price using inputUtility, show error if input is invalid
      /// </summary>
      /// <param name="price"></param>
      /// <returns></returns>
      private bool ValidatePrice(out double price)
      {
         // show error if input is invalid
         if (!InputUtility.GetDouble(txtPrice.Text.Trim(), out price, 0))
         {
            //inform user
            MessageBox.Show("Input of price is Invalid. It can not be less than 0, " + Environment.NewLine + "and must not be empty.", " Error!");

            txtPrice.Focus();
            txtPrice.Text = " ";
            txtPrice.SelectAll();
            return false;
         }
         return true;
      }

      /// <summary>
      /// Check if item is selected in listbox
      /// </summary>
      /// <returns></returns>
      private bool CheckSelectedIndex()
      {
         int index = lbSeats.SelectedIndex;
         if (index < 0)
         {
            MessageBox.Show("Please select an item in the box");
            return false;
         }
         else
            return true;
      }

      /// <summary>
      /// Call method ReserveOrCancelSeat when button OK is clicked
      /// </summary>
      /// <param name="sender"></param>
      /// <param name="e"></param>
      private void btnOK_Click(object sender, EventArgs e)
      {
         ReserveOrCancelSeat();
      }

      /// <summary>
      /// Reserve or cancel seat depending on choice the user makes. Update GUI after choice.
      /// </summary>
      private void ReserveOrCancelSeat()
      {
         if (CheckSelectedIndex() == true)
         {
            string name = string.Empty;
            double price = 0.0;
            int selectedSeat = lbSeats.SelectedIndex;
            bool reserve = false;
            bool cancel = false;

            if (rbReserve.Checked)
            {
               DialogResult result = MessageBox.Show("Do you want to continue?", "Approve", MessageBoxButtons.YesNo);
               if (result == DialogResult.Yes)
               {
                  if (ValidateInput(out name, out price))
                  {
                     reserve = seatMngr.ReserveSeat(name, price, selectedSeat);
                     if (reserve == true)
                     {
                         MessageBox.Show("Seat has been reserved");
                         UpdateGUI();
                     }
                     else
                     {
                        MessageBox.Show("Seat has already been reserved");
                     }
                  }
               }
            }
            else
            {
               DialogResult result = MessageBox.Show("Do you want to continue?", "Approve", MessageBoxButtons.YesNo);
               if (result == DialogResult.Yes)
               {
                  cancel = seatMngr.CancelSeat(selectedSeat);
                  if (cancel == true)
                  {
                     MessageBox.Show("Seat has been cancelled");
                     UpdateGUI();
                  }
                  else
                  {
                     MessageBox.Show("Seat is already vacant");
                  }
               }
            }
            UpdateGUI();
         }
      }

      /// <summary>
      /// Update GUI with new information. 
      /// </summary>
      /// <param name="customerName"></param>
      /// <param name="price"></param>
      private void UpdateGUI()
      {
         lbSeats.Items.Clear();
         lbSeats.Items.AddRange(seatMngr.GetSeatInfoString());
         lblVacantSeats.Text = seatMngr.GetNumOfVacant().ToString();
         lblReservedSeats.Text = seatMngr.GetNumOfReserved().ToString();

         if (rbReserve.Checked)
         {
            txtName.Text = string.Empty;
            txtPrice.Text = string.Empty;
         }
      }

      /// <summary>
      /// set textboxes to false if cancel reservation button is checked
      /// </summary>
      /// <param name="sender"></param>
      /// <param name="e"></param>
      private void rbCancel_CheckedChanged_1(object sender, EventArgs e)
      {
         txtName.Enabled = false;
         txtPrice.Enabled = false;
      }

      /// <summary>
      /// set textboxes to true if reserved radiobutton is checked
      /// </summary>
      /// <param name="sender"></param>
      /// <param name="e"></param>
      private void rbReserve_CheckedChanged_1(object sender, EventArgs e)
        {
            txtName.Enabled = true;
            txtPrice.Enabled = true;
        }

        /// <summary>
        /// Make necessary changes on the list depending on what choice the user makes. Show only 
        /// what the user wants to see, whether its all seats, reserved seats or vacant seats only.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void cmbOptions_SelectedIndexChanged(object sender, EventArgs e)
        {
           if (cmbOptions.SelectedIndex == 0 && rbReserve.Checked) //All seats visible.
           {
              UpdateGUI();
              txtName.Enabled = true;
              txtPrice.Enabled = true;
              btnOK.Enabled = true;
           }
           else if (cmbOptions.SelectedIndex == 0 && rbCancel.Checked)
           {
              UpdateGUI();
              txtName.Enabled = false;
              txtPrice.Enabled = false;
              btnOK.Enabled = true;
           }

           else if (cmbOptions.SelectedIndex == 1) //Only vacant seats visible.
           {
              lbSeats.Items.Clear();
              lbSeats.Items.AddRange(seatMngr.ReturnVacantSeats()); // Value cannot be null
              txtName.Enabled = false;
              txtPrice.Enabled = false;
              btnOK.Enabled = false;
           }

           else if (cmbOptions.SelectedIndex == 2) //Only reserved seats visible.
           {
              lbSeats.Items.Clear();
              lbSeats.Items.AddRange(seatMngr.ReturnReservedSeats()); // Value cannot be null
              txtName.Enabled = false;
              txtPrice.Enabled = false;
              btnOK.Enabled = false;
           }
        }
    }
}

座位管理器:

namespace Assignment4
{
   class SeatManager
   {
      private string[,] nameList = null;
      private double[,] priceList = null;
      private string[,] seatList = null;
      private readonly int totCols;
      private readonly int totRows;

      /// <summary>
      /// Constructor with declarations of size for all arrays.
      /// </summary>
      /// <param name="totNumberOfSeats"></param>
      public SeatManager(int row, int cols)
      {
         totCols = cols;
         totRows = row;

         nameList = new string[row, cols];
         priceList = new double[row, cols];
         seatList = new string[row, cols];

         for (int rows = 0; rows < row; rows++)
         {
            for (int col = 0; col < totCols; col++)
            {
                seatList[rows, col] = "Vacant";
            }
         }
      }
   }
}


/// <summary>
/// Check if index is within bounds of the array
/// </summary>
/// <param name="index"></param>
/// <returns></returns>
private bool CheckIndex(int index)
{
   if (index >= 0 && index < nameList.Length)
      return true;
   else
      return false;
}

/// <summary>
/// Return total number of seats
/// </summary>
/// <returns></returns>
public int GetNumOfSeats()
{
   int count = 0;

   for (int rows = 0; rows < totRows; rows++)
   {
      for (int cols = 0; cols < totCols; cols++)
      {
         count++;
      }   
   }
   return count;
}

/// <summary>
/// Calculate and return total number of reserved seats
/// </summary>
/// <returns></returns>
public int GetNumOfReserved()
{
   int totReservedSeats = 0;

   for (int rows = 0; rows < totRows; rows++)
   {
      for (int col = 0; col < totCols; col++)
      {
         if (!string.IsNullOrEmpty(nameList[rows, col]))
         {
            totReservedSeats++;
         }
      }
   }
   return totReservedSeats;
}

/// <summary>
/// Calculate and return total number of vacant seats
/// </summary>
/// <returns></returns>
public int GetNumOfVacant()
{
   int totVacantSeats = 0;

   for (int rows = 0; rows < totRows; rows++)
   {
      for (int col = 0; col < totCols; col++)
      {
         if (string.IsNullOrEmpty(nameList[rows, col]))
         {
            totVacantSeats++;
         }
      }
   }
   return totVacantSeats;
}

/// <summary>
/// Return formated string with info about the seat, name, price and its status
/// </summary>
/// <param name="index"></param>
/// <returns></returns>
public string GetSeatInfoAt(int index)
{
   int cols = ReturnColumn(index);
   int rows = ReturnRow(index);
   string strOut = string.Format("{0,2} {1,10} {2,17} {3,20} {4,35:f2}",
      rows+1, cols+1, seatList[rows, cols], nameList[rows, cols], priceList[rows, cols]);
   return strOut;
}

/// <summary>
/// Send an array containing all seats in the cinema
/// </summary>
/// <returns></returns>
public string[] GetSeatInfoString()
{
   int count = totRows * totCols;

   if (count <= 0)
      return null;

   string[] strSeatInfoStrings = new string[count];
   for (int i = 0; i < totRows * totCols; i++)
   {
      strSeatInfoStrings[i] = GetSeatInfoAt(i);
   }
   return strSeatInfoStrings;
}

/// <summary>
/// Reserve seat if seat is vacant
/// </summary>
/// <param name="name"></param>
/// <param name="price"></param>
/// <param name="index"></param>
/// <returns></returns>
public bool ReserveSeat(string name, double price, int index)
{
   int cols = ReturnColumn(index);
   int rows = ReturnRow(index);
   if (string.IsNullOrEmpty(nameList[rows, cols]))
   {
      nameList[rows, cols] = name;
      priceList[rows, cols] = price;
      seatList[rows, cols] = "Reserved";
      return true;
   }
   else
      return false;
}

public string[] ReturnVacantSeats()
{
   int totVacantSeats = int.Parse(GetNumOfVacant().ToString());
   string[] vacantSeats = new string[totVacantSeats];
   for (int i = 0; i < vacantSeats.Length; i++)
   {
      if (GetSeatInfoAt(i) == "Vacant")
      {
         vacantSeats[i] = GetSeatInfoAt(i);
      }
   }
   return vacantSeats;
}

public string[] ReturnReservedSeats()
{
   int totReservedSeats = int.Parse(GetNumOfReserved().ToString());

   string[] reservedSeats = new string[totReservedSeats];
   for (int i = 0; i < reservedSeats.Length; i++)
   {
      if (GetSeatInfoAt(i) == "Reserved")
      {
         reservedSeats[i] = GetSeatInfoAt(i);
      }
   }
   return reservedSeats;
}

/// <summary>
/// Cancel seat if seat is reserved
/// </summary>
/// <param name="index"></param>
/// <returns></returns>
public bool CancelSeat(int index)
{
   int cols = ReturnColumn(index);
   int rows = ReturnRow(index);

   if (!string.IsNullOrEmpty(nameList[rows, cols]))
   {
      nameList[rows, cols] = "";
      priceList[rows, cols] = 0.0;
      seatList[rows, cols] = "Vacant";
      return true;
   }
   else
   {
      return false;
   }
}

/// <summary>
/// Convert index to row and return value
/// </summary>
/// <param name="index"></param>
/// <returns></returns>
public int ReturnRow(int index)
{
   int vectorRow = index;
   int row;
   row = (int)Math.Ceiling((double)(vectorRow / totCols));
   return row;
}

/// <summary>
/// Convert index to column and return value
/// </summary>
/// <param name="index"></param>
/// <returns></returns>
public int ReturnColumn(int index)
{
   int row = index;
   int col = row % totCols;
   return col;
}

在 MainForm 中,这是我得到 ArgumentNullException 的地方:

lbSeats.Items.AddRange(seatMngr.ReturnVacantSeats());

这是返回包含所有空座位的数组的方法:

public string[] ReturnVacantSeats()
{
   int totVacantSeats = int.Parse(GetNumOfVacant().ToString());
   string[] vacantSeats = new string[totVacantSeats];
   for (int i = 0; i < vacantSeats.Length; i++)
   {
      if (GetSeatInfoAt(i) == "Vacant")
      {
         vacantSeats[i] = GetSeatInfoAt(i);
      }
   }
   return vacantSeats;
}
4

1 回答 1

2

伍利,

注释表明您由于该if语句而存在 null 问题,因此,您需要避免在 addrange 调用中添加包含 null 的值。选项 #1 将更改lbSeats.Items.AddRange(seatMngr.ReturnVacantSeats());.

在这里,您可以沿(未经测试的代码)的行添加“Where”子句:

lbSeats.Items.AddRange(seatMngr.ReturnVacantSeats()
    .Where(x => !string.IsNullOrEmpty(x)));

如果您不想这样做,您可以使用默认的空字符串值设置初始数组(这将防止空异常)。

选项#2(更改):

string[] vacantSeats = new string[totVacantSeats];

至:

string[] vacantSeats = Enumerable.Repeat(string.Empty,totVacantSeats).ToArray(); 

乱七八糟的 frig,可能会起作用,可能完全是 b@llocks,但现在可能会让你克服错误。

当然(在当前代码中)的替代方案是选项#3:

if (GetSeatInfoAt(i) == "Vacant")
{
    vacantSeats[i] = GetSeatInfoAt(i);
} else {
    vacantSeats[i] = string.empty;
}

呸...

于 2013-10-31T22:20:34.877 回答