Ссылка на объект не указывает на экземпляр класса
Хотел сделать класс(Box), в котором поля(name, age, length) вводились бы с form-ы, а потом находилось бы максимальное значение поля lenght и через MessageBox отправлялось бы сообщение имени самого высокого человека.
public Box(string name, int width, int length, int weight, int age) => NewPers = name;
public int Len //как я понял, здесь я добавляю свойство, чтобы обращаться к приватному параметру length с других блоков программы
{
get {
return length;
}
set {
length = value;
}
}
public string NewPers
{
get => name[counter];
set
{
name[counter] = value;
}
}
}
private void button1_Click(object sender, EventArgs e)
{
Box[] NameBox = new Box[5]; //создаю объекты класса Box
for (int i = 0; i < 5; i++)
{
if (NameBox[i] != null) //если значение не равно нулю, то продолжаем
continue;
NameBox[i] = new Box(textBox1.Text, int.Parse(textBox2.Text), int.Parse(textBox3.Text), int.Parse(textBox4.Text), int.Parse(textBox5.Text));
break;
}
for (int j = 0; j <= NameBox.Length; j++)
{
if (max < NameBox[j].Len)
{
max = NameBox[j].Len;
}
}
MessageBox.Show( $"Максимальный рост у человека {max}");
}
}
P.S. Вообщем я позавчера решил познакомиться поближе, пока еще мало что понимаю => возможно, вообще ерунду пишу. Не забывайте про комментарии, пожалуйста
Ответы (3 шт):
Ссылка на объект не указывает на экземпляр класса - вы обращаетесь к объекту который не инициализирован
вот как должно быть
По порядку сам класс
class Human
{
public string Name { get; set; }
public double Width { get; set; }
public double Height { get; set; }
public double Weight { get; set; }
public int Age { get; set; }
//ctor empty
public Human()
{
}
//ctor with params
public Human(string name, string width, string height, string weight, string age)
{
Name = name;
Width = Convert.ToDouble(width);
Height = Convert.ToDouble(height);
Weight = Convert.ToDouble(weight);
Age = Convert.ToInt32(age);
}
//ctor with params for textbox
public Human(TextBox name, TextBox width, TextBox height, TextBox weight, TextBox age)
{
Name = name.Text;
Width = Convert.ToDouble(width.Text);
Height = Convert.ToDouble(height.Text);
Weight = Convert.ToDouble(weight.Text);
Age = Convert.ToInt32(age.Text);
}
}
теперь его реализация
public partial class Form1 : Form
{
List<Human> _humans = new List<Human>();//создаем список с нашим классом
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
Human human1 = new Human("imja1", "10", "110", "10", "10");// создаем экземпляр класса
_humans.Add(human1);//добавляем его в список
Human human2 = new Human("imja2", "20", "120", "20", "20");
_humans.Add(human2);
Human human3 = new Human("imja3", "30", "130", "30", "30");
_humans.Add(human3);
Human human4 = new Human("imja4", "40", "140", "40", "40");
_humans.Add(human4);
Human human5 = new Human("imja5", "50", "150", "50", "50");
_humans.Add(human5);
}
//кнопка добавить человека в список
private void button1_Click(object sender, EventArgs e)
{
Human human = new Human(textBox1,textBox2,textBox3,textBox4,textBox5);//тут указываем переменные Texbox
_humans.Add(human);
}
//кнопка найти человака с самым большим ростом
private void button2_Click(object sender, EventArgs e)
{
Human result = _humans.Find(x => x.Height == _humans.Max(z => z.Height));// ишем человека с саммым высоким ростом
MessageBox.Show(result.Name);// показываем его имя
}
}
Для простоты я ваш класс Box урезал до двух свойств (остальные там просто не использовались) будет не сложно их добавить. Во первых зачем вы каждый раз создаете массив Box[] NameBox = new Box[5]; ? цикл заполнения тоже очень странный, да и не нужный в принципе. Вообще проще использовать список, советую их изучить. Сделайте вторую кнопку "сброс" подклчите к ней обработчик button2_Click для сброса массива.
свойства можно объявлять без переменных(их создаст компилятор);
для сравнения удобно использовать шаблон IComparable;
конвертировать типы желательно через TryParse с проверкой на ошибку;
ф-я Max() - из linq, если не знакомы очень советую изучить, это очень мощный инструмент;
private int _curIndex; private Box[] _boxes = new Box[5]; private void button1_Click(object sender, EventArgs e) { if (_curIndex == _boxes.Length) { MessageBox.Show($"Массив полностью заполнен"); return; } if (!int.TryParse(textBox2.Text, out var len)) { MessageBox.Show($"Рост указан не верно"); return; } _boxes[_curIndex] = new Box(textBox1.Text, len); _curIndex++; var maxHighBox = _boxes.Max(); MessageBox.Show($"Максимальный рост у человека {maxHighBox.Name} - {maxHighBox.Len}"); } private void button2_Click(object sender, EventArgs e) { _curIndex = 0; _boxes = new Box[5]; } public class Box : IComparable<Box> { public int Len { get; } public string Name { get; } public Box(string name, int len) { Len = len; Name = name; } public int CompareTo(Box other) => Len.CompareTo(other.Len); }
После создания массива все его элементы будут null - поэтому нет смысла проверять в цикле
NameBox[i] != null
это выражение всегда вернет false
break - прерывает выполнение цикла. В данном случае цикл всегда прерывается после первой итерации.
Таким образом инициализируется всегда только нулевой элемент.
Поэтому во втором цикле попытка взять
NameBox[j].Len
у любого элемента с индексом больше 0 будет приводить к указанной ошибке.
