This is one of the most common problems we get asked, and it's also the one we are least equipped to answer, but you are most equipped to answer yourself.
Let me just explain what the error means: You have tried to use a variable, property, or a method return value but it contains null - which means that there is no instance of a class in the variable.
It's a bit like a pocket: you have a pocket in your shirt, which you use to hold a pen. If you reach into the pocket and find there isn't a pen there, you can't sign your name on a piece of paper - and you will get very funny looks if you try! The empty pocket is giving you a null value (no pen here!) so you can't do anything that you would normally do once you retrieved your pen. Why is it empty? That's the question - it may be that you forgot to pick up your pen when you left the house this morning, or possibly you left the pen in the pocket of yesterday's shirt when you took it off last night.
We can't tell, because we weren't there, and even more importantly, we can't even see your shirt, much less what is in the pocket!
Back to computers, and you have done the same thing, somehow - and we can't see your code, much less run it and find out what contains null when it shouldn't.
But you can - and Visual Studio will help you here. Run your program in the debugger and when it fails, VS will show you the line it found the problem on. You can then start looking at the various parts of it to see what value is null and start looking back through your code to find out why. So put a breakpoint at the beginning of the method containing the error line, and run your program from the start again. This time, VS will stop before the error, and let you examine what is going on by stepping through the code looking at your values.
And here is where it gets complicated.
Basically, the problem is that you are using structs, which are value types while classes are reference types.
So when you use the value of any of your structs, you copy the value rather than taking a reference. So this code:
Student myStudent = myClass.Array1[i];
Console.WriteLine("Enter first name");
myStudent.firstName = Console.ReadLine();
Creates a copy of the Student in the Array1, gets a a first name, and puts it into the copy - that doesn't in any way affect the original version in the Array1.
So when you use the Array version later there is nothing there; no information at all.
I'm not going to try and fix that for you - this is important and complicated, and you need to understand what is going on - so I'll suggest you have a look at this: Using struct and class - what's that all about?
It gets a bit advanced for you, but it hopefully covers what you are doing and why it's failing so badly when it looks so right!
And do yourself a couple of favours:
Don't call anything "Class" as it's too close to
the keyword, and definitely don't call a
Use sensible names for things:
is fine. But
? If you call them
your code becomes a lot more readable!
Don't worry too much about this right now, but remember it: never use
methods on user input because users make mistakes, and the
methods cause your app to fail when that happens - and users like nothing less than typing a list of names and courses and grades only to have the app crash because they accidentally typed a comma instead of a full stop ...
When you have a little more experience, look at the
methods instead: Int32.TryParse Method (System) | Microsoft Docs
], Double.TryParse Method (System) | Microsoft Docs
], DateTime.TryParse Method (System) | Microsoft Docs
] - they allow you to check and convert user input without making your app fail!