0

I've been battling for some times now with a little problem which I think has a very easy solution; but can't find it. Maybe I couldn't get the right way to formulate my question on Google... Anyways, I went around it but the way I've done it is very inelegant and cumbersome. What I really want to do would be something like this:

Public Class Form1
Public Class my_classOne
    Public the_name As String = ""
    Public the_surname As String = ""
End Class

Public Class my_classTwo
    Inherits my_classOne
    Public a_table(10) As my_classOne
    Public a_thing As New my_classOne
End Class


Public the_record As New my_classTwo

Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    Dim i As Integer
    For i = 1 To 10
        the_record.a_table(i).the_name = "Name is:" + i.ToString
        Label1.Text = the_record.a_table(i).the_name
        the_record.a_thing.the_name = "Name: " + i.ToString
        Label1.Text = the_record.a_thing.the_name
    Next
End Sub
End Class

I get, when debugging, the error shown in the picture on that line of code:

the_record.a_table(i).the_name = "Name is:" + i.ToString

What do I do wrong? How can I get a_table() in my_classTwo to inherit from my_classOne?

enter image description here

NorKayak
  • 41
  • 7
  • You should review [this question](https://stackoverflow.com/questions/4660142/what-is-a-nullreferenceexception-and-how-do-i-fix-it). – jmcilhinney May 04 '21 at 05:00
  • This is obviously test/demo code but there are some issues there that you definitely should not repeat in real/production code, so I figured that I would address them here. Firstly, all those fields should be properties. Secondly, there seems no good reason that `my_classTwo` should be inheriting `my_classOne`. – jmcilhinney May 04 '21 at 05:06
  • Most relevant to you, though, is the fact that you should rarely be exposing arrays publicly like that. Generally speaking, you should use a collection type and make the property `ReadOnly`. That way, the calling code can get the collection to get, add and remove items, but it cannot replace the existing collection with a completely new one. That's how it's done throughout the .NET Framework, e.g. `Control.Controls`, `DataSet.Tables`, `DataTable.Columns`, `DataTable.Rows`, `ListBox.Items`, `ComboBox.Items`, `ListView.Items`, `ListView.Columns`, `ListView.Groups`, etc, etc. – jmcilhinney May 04 '21 at 05:10
  • But it's when I try to put thing in that array that I get a error message! – NorKayak May 04 '21 at 05:28
  • No it isn't. Use your head. You are trying to get something out, not put something in. You are trying to GET the element at index `i` and set a field of that object but there is no object because you never SET the element at that index. – jmcilhinney May 04 '21 at 05:30

3 Answers3

1

This line:

Public a_table(10) As my_classOne

creates an array with 11 elements but, as is always the case, each of those elements is Nothing by default. Nowhere in your code do you set those elements, therefore this line:

the_record.a_table(i).the_name = "Name is:" + i.ToString

is trying to set the the_name property of an object that doesn't exist because a_table(i) is Nothing.

This is always the way it is with a NullReferenceException so all you need to do is debug your code properly and determine which reference is null and then work backwards to where you intended to set that reference to something.

EDIT:

This:

the_record.a_table(i).the_name = "Name is:" + i.ToString

is functionally equivalent to this:

Dim x = the_record.a_table(i)

x.the_name = "Name is:" + i.ToString

Clearly, you are GETting something from the array, not SETting something. What you're doing is akin to putting a jumper on a passenger on a bus when there's no one on the bus. How can you put a jumper on a person that doesn't exist? You can't and that should be obvious to anyone. This is the same situation as your code. You can't set a field of an object in an array if you never put any objects into the array in the first place. This is not rocket surgery. If you put nothing in then you get nothing out. PUT SOMETHING IN!

jmcilhinney
  • 50,448
  • 5
  • 26
  • 46
  • Thanks to trying to help. But you are skipping classes with me as I'm a bit of a beginner. Do you mean I should rather have something lie this ´Public a_table(10) As New my_classOne´ ? But that doesn't work either. – NorKayak May 04 '21 at 05:20
  • @NorKayak, no, of course that wouldn't work, because it's invalid syntax. I have explained the reason that you are seeing the exception you reported and have told you how to fix it: set the elements of the array. If you don't understand something that basic then it is you who are skipping things, not me. This is not a place to come for a beginner tutorial on how to work with arrays. If you don't know how arrays work and how to use them, you need to do some research on that and learn. – jmcilhinney May 04 '21 at 05:24
  • The code I put above is only for example, to make the matter short and so people can see easily where my mistake is. So my question is where do I modify that code so that it does what I expect it to do.? – NorKayak May 04 '21 at 05:26
  • @NorKayak, that said, consider this: if I made an egg carton and gave it to you and told you to make me an omelette, could you do it? Of course you couldn't! How are you supposed to get eggs out of an egg carton if no eggs are put into it in the first place? The fact that you have an egg carton doesn't mean that you magically have eggs. – jmcilhinney May 04 '21 at 05:26
  • @NorKayak, *"where do I modify that code"*. That's up to you. Stop expecting us to design your app for you. The problem is that you never put anything into your array. Where do you want to put something into your array? That's where you modify the code. It's for you to decide, not us. – jmcilhinney May 04 '21 at 05:27
  • @ jmcilhinney But I declare a_table as my_classOne so it's not empty it's something, no? – NorKayak May 04 '21 at 05:36
  • @NorKayak, see the edit to my question and spend a bit of time learning the basics of how classes, reference types and arrays work. An array element is just like a variable, which means it is `Nothing` by default. If you never set it, it remains `Nothing`. If you expect it to be something, set it to something. – jmcilhinney May 04 '21 at 05:36
  • @NorKayak, how about you actually read what I'm telling you. I never said that `a_table` was `Nothing`. That field refers to an array object. That object is the egg carton or the bus, depending on which of my analogies you prefer. As I stated several times, the issue is that all the elements of that array are `Nothing`, just as an egg carton contains no eggs unless you put some in and a bus contains no passengers unless some board. I'm done here. You need to make the effort to learn how arrays work. – jmcilhinney May 04 '21 at 05:39
  • @ jmcilhinney Thanks for trying. – NorKayak May 04 '21 at 05:41
0

After looking around and a little help here is what i should have done:

Public Class Form1
Public Class my_classOne
    Public the_name As String = ""
    Public the_surname As String = ""
End Class

Public Class my_classTwo
    Inherits my_classOne
    Public a_table(10) As my_classOne
    Public a_thing As New my_classOne
End Class


Public the_record As New my_classTwo

Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    Dim i As Integer
    For i = 0 To 10
        the_record.a_table(i) = New my_classOne
        the_record.a_table(i).the_name = "Name is:" + i.ToString
        Label1.Text = the_record.a_table(i).the_name
        the_record.a_thing.the_name = "Name: " + i.ToString
        Label1.Text = the_record.a_thing.the_name
    Next
End Sub
End Class
NorKayak
  • 41
  • 7
0

Please see in line comments.

Remember .net arrays and collections are 0 based. vb.net arrays are declared arrayName(UpperBoundIndex). Just to confuse us C# arrays are declared arrayName[NumberOfElements].

Public Class my_classOne
    Public the_name As String = ""
    Public the_surname As String = ""
End Class

Public Class my_classTwo
    'The following creates an array capable of holding 11 instances of the my_classOne Class.
    'Currently each element of the array in Nothing (null)
    Public a_table(10) As my_classOne
    Public a_thing As New my_classOne
    Public Sub New()
        'This initializes the 11 elements of the array
        For i = 0 To 10
            a_table(i) = New my_classOne
        Next
    End Sub
End Class

Public the_record As New my_classTwo

Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    Dim i As Integer
    For i = 0 To 10
        the_record.a_table(i).the_name = "Name is:" + i.ToString
        Label1.Text = the_record.a_table(i).the_name 'You are just overwriting the contents
        'of the label on each iteration. 
        'On the next line you are overwriting the "the_name" property of each element.
        the_record.a_thing.the_name = "Name: " + i.ToString
        Label1.Text = the_record.a_thing.the_name
        'Only the last value will be visible to the user.
    Next
End Sub
Mary
  • 14,926
  • 3
  • 18
  • 27