NullReferenceException?为什么?[关闭]

NullReferenceException? Why? [closed]

提问人:NotSoGoodProgrammer 提问时间:2/19/2022 更新时间:2/19/2022 访问量:77

问:


编辑问题以包括所需的行为、特定问题或错误以及重现问题所需的最短代码。这将帮助其他人回答这个问题。

去年关闭。

我尝试在 calc_total_age() 中计算乘客的总年龄,这在我添加乘客并写出“0”之前有效。但是,当我添加乘客时,我得到 NullReferenceException,我尝试了不同的事情,但我就是无法理解我正在做的事情。我需要朝着正确的方向前进,也许并解释我在做什么,我不知道我的 GetAge() 是做什么的,我真的试图称呼它,但它似乎不起作用。 这是我的全部代码:

using System;
using System.Linq;
using System.Text;
using System.Collections.Generic;
using System.Threading.Tasks;

class Program {
  public static void Main (string[] args) {

    //Console.Clear();
    Console.WriteLine("Hi, welcome to the Buss-Simulator!");
    Console.ReadKey();
   

   var mybus = new Bus();
   mybus.Run();

   Console.ReadKey();
   
  }
}
using System;
using System.Linq;
using System.Text;
using System.Collections.Generic;
using System.Threading.Tasks;

class Bus {

    public int total_passengers = 0;
    public Passenger[] info_passengers;
    public int totalAge = 0;
    public int totalSeats = 25;
    
    

    public void Run()
    {
      
      info_passengers = new Passenger[25];

      string [] menu = new string[]{"1. Pick up passenger.", "2. Show who's on the bus.", "3. Calculate total age of passengers"};
      int MenuSelect = 0;
    
      while (true)
      {
        Console.Clear();
        Console.WriteLine("What do you want to do?");
        Console.WriteLine();
        Console.CursorVisible = false;
        
        if (MenuSelect == 0)
        {
          Console.WriteLine(menu[0] + " ⭅");
          Console.WriteLine(menu[1]);
          Console.WriteLine(menu[2]);
        }
        else if(MenuSelect == 1)
        {
          Console.WriteLine(menu[0]);
          Console.WriteLine(menu[1] + " ⭅");
          Console.WriteLine(menu[2]);
        }
        else if(MenuSelect == 2)
        {
          Console.WriteLine(menu[0]);
          Console.WriteLine(menu[1]);
          Console.WriteLine(menu[2] + " ⭅");
        }
        
        var keyPressed = Console.ReadKey();

        if(keyPressed.Key == ConsoleKey.DownArrow && MenuSelect != menu.Length -1)
        {
          MenuSelect++;
        }
        else if (keyPressed.Key == ConsoleKey.UpArrow && MenuSelect >= 1)
        {
          MenuSelect--;
        }
        else if (keyPressed.Key == ConsoleKey.Enter)
        {
          switch (MenuSelect)
          {
            case 0:
              add_passengers();
              break;
            case 1:
              print_passengers();
              break;
            case 2:
              calc_total_age();
              break;
          }
        }
      }
    }


  public void add_passengers()
  {
    if (total_passengers == 25)
    {
    Console.WriteLine("\nBus is full!");
    System.Threading.Thread.Sleep(2000);
    return;
    }

    try
    {
      Console.WriteLine("\nType the name, age & gender of your passenger.");

      Console.Write("\nName: ");

      string name = Console.ReadLine();

      Console.Write("\nAge: ");

      int age = Convert.ToInt32(Console.ReadLine());

      Console.Write("\nGender: ");

      string gender = Console.ReadLine();

      Passenger passenger = new Passenger(aName: name, aAge: age, aGender: gender);

      Array.Resize(ref info_passengers, info_passengers.Length + 1);

      info_passengers[info_passengers.Length - 1] = passenger;
    }

    catch (Exception e)
    {
      Console.WriteLine("\nFollow instructions.");
      System.Threading.Thread.Sleep(2000);
      return;
    }

    total_passengers++;
    Console.WriteLine("You boarded 1 Passenger." + "\nThere are " + (totalSeats - total_passengers) + " seats left.");
    System.Threading.Thread.Sleep(2000);
    return;
  }
    
  
  
    public void print_passengers()
    {
      Console.WriteLine();
      foreach (var i in info_passengers)
      {
        Console.WriteLine(i);
      }
      Console.ReadKey();
    }

    public void calc_total_age()
    {
      for (int i = 0; i < total_passengers; i++)
      {
        totalAge += info_passengers[i].age;
      }
    Console.WriteLine(totalAge);
    Console.ReadKey();
    } 
}
using System;
using System.Linq;
using System.Text;
using System.Collections.Generic;
using System.Threading.Tasks;

class Passenger{

  public string name;
  public int age;
  public string gender;

  public Passenger(string aName,  int aAge, string aGender)
  {
    name = aName;
    age = aAge;
    gender = aGender;
  }
  
  public override string ToString()
  {
    return string.Format($"This is {name}, {gender}, {age} years old.");
  }

  public int GetAge()
  {
    return age;
  }
  

}
C# 数组 NullReferenceException

评论

1赞 Caius Jard 2/19/2022
我不确定我是否每次都会调整数组的大小;我只是坚持增加total_passengers,这样它就会不断跟踪公共汽车上有多少人;将 Passenger 数组保留为长度为 25(公交车容量)的数组 - total_passengers因此也会跟踪存储下一位乘客的位置。实际上,您似乎将数组的大小从 25 调整到 26 等,然后将新乘客存储在最后一个索引中,因此数组开头有 25 个空(空)插槽
0赞 NotSoGoodProgrammer 2/19/2022
好吧,我删除了这两行,但在添加乘客后仍然收到相同的错误。:s Array.Resize(ref info_passengers, info_passengers.长度 + 1);, info_passengers[info_passengers.长度 - 1] = 乘客;
0赞 Caius Jard 2/19/2022
如果你删除了这两个生命,还剩下哪一行代码把你的新乘客藏在数组中?
0赞 NotSoGoodProgrammer 2/19/2022
哈哈,我明白你的意思了,删除后没有检查print_passengers所以没看出有什么问题。又加回来了。谢谢!
0赞 Aluan Haddad 2/19/2022
不要发现任意的异常,尤其是在学习一门新语言时

答:

0赞 debater 2/19/2022 #1

这个问题的答案很简单!

您声明:

public Passenger[] info_passengers;

这实际上会创建一个指向数组的指针,该数组(与所有针一样)最初为 null。它不会创建实际的数组本身。Passenger

当您的代码调用时:

Array.Resize(ref info_passengers, info_passengers.Length + 1);

该方法要求 Array 参数指向数组。但是,仍为 null。所以你得到了例外。Resizeinfo_passengers

我认为您需要做的就是初始化为一个新的空数组,如下所示:info_passengers

public Passenger[] info_passengers = new Passenger[]();

然后我认为一切都会奏效的。

评论

4赞 Caius Jard 2/19/2022
所以 Run() 的第一行没有吗?
0赞 NotSoGoodProgrammer 2/19/2022
尝试添加一个空数组,它只是说数组不能为空。:/
1赞 Serge 2/19/2022 #2

您不需要调整数组的大小info_passengers因为它对于总路过者来说已经足够了。添加额外的数组单元格时,会在 arry 的末尾添加一个 passanger,但在数组的开头中仍然有导致异常的 null 的空单元格。

所以删除这个代码

 Array.Resize(ref info_passengers, info_passengers.Length + 1);

并修复此问题

 total_passengers++;
 info_passengers[ total_passengers-1] = passenger;

并且不要忘记删除total_passengers++;从这里开始

 Console.WriteLine("You boarded 1 Passenger." + "\nThere are " + (totalSeats - total_passengers) + " seats left.");

并在 calc_total_age 中添加 totalAge=0

public void calc_total_age()
    {
       totalAge=0;
      for (int i = 0; i < total_passengers; i++)
      {
        totalAge += info_passengers[i].age;
      }

在你的捕获块中隐藏错误并不是一个好主意。我会做到的

catch (Exception e)
    {
      Console.WriteLine("\n Error!!! " + e.Message);
      System.Threading.Thread.Sleep(2000);
      return;
    }

评论

0赞 NotSoGoodProgrammer 2/19/2022
我删除了 ,并更改了 ,以添加“totalSeats--;”并删除了“totalSeats - total_passengers”,但随后 catch 触发并显示“遵循说明”,即使它输入正确。Array.Resize(ref info_passengers, info_passengers.Length + 1);info_passengers[info_passengers - 1] = passenger;info_passengers[ total_passengers-1] = passenger;
0赞 Serge 2/19/2022
在我的回答中,我没有要求“totalSeats--和totalSeats - total_passengers”。只需按照答案操作即可
0赞 Serge 2/19/2022
@NotSoGoodProgrammer totalSeats 应为常量。这是同一辆公共汽车,座位没有变化。传代人正在改变
0赞 NotSoGoodProgrammer 2/19/2022
然后我误解了你说的“不要忘记删除 total_passengers++;从这里开始“,我只添加了totalSeats,以便用户可以看到他们还有多少乘客要添加。Console.WriteLine("You boarded 1 Passenger." + "\nThere are " + (totalSeats - total_passengers) + " seats left.");
0赞 Serge 2/19/2022
@NotSoGoodProgrammer 是的,只需删除 total_passengers++;在 Console.Write 之前。但是我没有把totalSeats--你现在有什么错误?