Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

Data class NullReferenceException

Discussion in 'Getting Started' started by aMIGA_dUDE, Jun 26, 2022.

  1. aMIGA_dUDE

    aMIGA_dUDE

    Joined:
    Oct 12, 2019
    Posts:
    21
    I got be doing some thing that going that obvious wrong, but don't looking at the problem for to long. All I get is this error message NullReferenceException: Object reference not set to an instance of an object

    In my mind there nothing wrong here, please enlightened me and show me my Doh. Dont want to pull my hair out anymore and end up looking like Homer Simpson ;)
    Code (CSharp):
    1. using UnityEngine;
    2.  
    3. public class testW3 : MonoBehaviour
    4. {
    5.     int int_Data;
    6.     TestW3_data testW3_Data;
    7.  
    8.     int[] int_DataArray = new int[12];
    9.     TestW3_data[] testW3_DataArray = new TestW3_data[123];
    10.  
    11.     void Start()
    12.     {
    13.         int indextotest = 5;
    14.  
    15.         int_Data = 666;
    16.         Debug.Log($"int_Data {int_Data}");
    17.        
    18.         testW3_Data.code = 555; // ? NullReferenceException: Object reference not set to an instance of an object
    19.         Debug.Log($"testW3_Data.code {testW3_Data}");
    20.  
    21.  
    22.         Debug.Log("Array Test");
    23.         Debug.Log("Test intdata");
    24.         int_DataArray[indextotest] = 777;
    25.         Debug.Log($"IndexToTest {indextotest} {int_DataArray} length {int_DataArray.Length} , {testW3_DataArray} length {testW3_DataArray.Length}");
    26.         testW3_DataArray[indextotest].code = 55;  // ? NullReferenceException: Object reference not set to an instance of an object
    27.         Debug.Log("It all Worked!");
    28.     }
    29. }
    30.  
    31. public class TestW3_data
    32. {
    33.     private int _code;
    34.     public int code
    35.     {
    36.         get { return _code; }
    37.         set { _code = value; }
    38.     }
    39. }
     
  2. aMIGA_dUDE

    aMIGA_dUDE

    Joined:
    Oct 12, 2019
    Posts:
    21
    Think worked it out. I took little break and there my solution to the issue. Someone might find FixArrayIfNull soution useful.
    So have any of you got any better solutions?

    Code (CSharp):
    1. using UnityEngine;
    2.  
    3. public class testW3 : MonoBehaviour
    4. {
    5.     int int_Data;
    6.     TestW3_data testW3_Data = new TestW3_data();
    7.  
    8.     int[] int_DataArray = new int[12];
    9.     TestW3_data[] testW3_DataArray = new TestW3_data[123];
    10.  
    11.     void Start()
    12.     {
    13.         int indextotest = 5;
    14.  
    15.         int_Data = 666;
    16.         Debug.Log($"int_Data {int_Data}");
    17.         Debug.Log("TEST 1 " + testW3_Data);
    18.         testW3_Data.code = 555; // ? NullReferenceException: Object reference not set to an instance of an object
    19.         Debug.Log($"testW3_Data.code {testW3_Data.code}");
    20.  
    21.  
    22.         Debug.Log("Array Test");
    23.         Debug.Log("Test intdata");
    24.         int_DataArray[indextotest] = 777;
    25.  
    26.         // Doing an check find out where it is Null
    27.         Debug.Log((testW3_DataArray == null ? "1_A-Null" : "1_A-Initialize"));
    28.         Debug.Log(testW3_DataArray[indextotest] == null ? "2_B-Null" : "2_B-Initialize");
    29.         //Debug.Log((testW3_DataArray[indextotest].code == null ? "5_C-Null" : "5_C-Initialize")); // will make it crash if null
    30.         testW3_DataArray[indextotest] = new TestW3_data();
    31.         FixArrayIfNull(ref testW3_DataArray);
    32.         Debug.Log((testW3_DataArray == null ? "3_A-Null" : "3_A-Initialize"));
    33.         Debug.Log(testW3_DataArray[indextotest] == null ? "4_B-Null" : "4_B-Initialize");
    34.         Debug.Log((testW3_DataArray[indextotest].code == null ? "5_C-Null" : "5_C-Initialize"));
    35.         testW3_DataArray[indextotest] = new TestW3_data();
    36.  
    37.         Debug.Log($"IndexToTest {indextotest} {int_DataArray} length {int_DataArray.Length} , {testW3_DataArray} length {testW3_DataArray.Length}");
    38.         testW3_DataArray[indextotest].code = 55;  // ? NullReferenceException: Object reference not set to an instance of an object
    39.         Debug.Log("It all Worked!");
    40.     }
    41.  
    42.     void FixArrayIfNull<T>(ref T[] _object) where T : new()
    43.     {
    44.         for (int i = 0; i < _object.Length; i++)
    45.         {
    46.             if (_object[i] == null)
    47.             {
    48.                 T t = new T();
    49.                 _object[i] = t;
    50.             }
    51.             /*
    52.             else
    53.             {
    54.                 Debug.Log($"Skiping as it Initialize [{i}] : {_object}");
    55.             }
    56.             */
    57.         }
    58.     }
    59. }
    60.  
    61. public class TestW3_data
    62. {
    63.     private int _code;
    64.     public int code
    65.     {
    66.         get { return _code; }
    67.         set { _code = value; }
    68.     }
    69. }
    70.  
     
  3. Schneider21

    Schneider21

    Joined:
    Feb 6, 2014
    Posts:
    3,510
    On line 18 you're accessing the code property of the array itself. I would never expect this to work, as (I assume) the code property is actually a member of your TestW3_data class and not the array itself.

    On line 38 you're accessing an index in that array directly (the 6th item, based on what you set on line 13) but if you didn't set anything there explicitly in that position in the Inspector, it's going to be a null value, which you're then trying to access the code property from (which makes sense that it would be null).

    All your "fix if null" solution is doing is checking if there are values in your array and if not, creating a new instance for that slot. Which is fine, but... based on your code I would expect that value to be null on line 38, and like I said I'd never expect line 18 to compile.

    I can't get a good sense of your C# or general programming knowledge from this code, so accept my apologies if this offends, but: what's your comfort level with writing code? Do you understand how arrays and objects work?
     
  4. aMIGA_dUDE

    aMIGA_dUDE

    Joined:
    Oct 12, 2019
    Posts:
    21
    Left this for few days to refect upon your comment. Which I think think was good thing do (no need to burn bridges etc).
    My comfort level is alright, but never there no such thing as know all need to know. But I would say just a beginer.

    An array is predefind amount of memory. This reasion why arrays are so much quick look up then list. Say some data defined as using 3 bytes in size. You want to know what is array [57] all that happend is look up start memory address say 1000, then take size of 3 and then multiple by 57 which give address of 1171.
    Object are just form of abstraction.

    Is there something that missing or am I getting this wrong?
     
  5. JeffDUnity3D

    JeffDUnity3D

    Unity Technologies

    Joined:
    May 2, 2017
    Posts:
    14,446
    What do you mean by "address"? You access array elements like this:

    myValue = myArray[57];

    This code is incorrect, there is no code property.

    testW3_Data.code = 555;
     
  6. aMIGA_dUDE

    aMIGA_dUDE

    Joined:
    Oct 12, 2019
    Posts:
    21
    When stated "address" it was short hand for "memory address". Would be able to elaborate upon your meaning "code property.

    As I understand it an Array uses contiguous memory alication. Unlike List has list for where each record is stored in memory.
     
  7. JeffDUnity3D

    JeffDUnity3D

    Unity Technologies

    Joined:
    May 2, 2017
    Posts:
    14,446
    Arrays don't use/need the concept of memory addresses based on datatype sizes.

    Regarding "code", you wrote this:

    testW3_Data.code

    There is no "code" property in your testW3_Data object which is an array. So remove that line.
     
  8. Schneider21

    Schneider21

    Joined:
    Feb 6, 2014
    Posts:
    3,510
    I made the same mistake. They're actually accessing the property on the testW3_Data object, not int_DataArray array. Maaaaybe not the best naming scheme if it fooled two of us, lol.

    It actually looks to me like this code should compile fine, and I'm thinking that it does and it's actually runtime exceptions happening (which is what OP put in the comments).

    If that's the case, does it have something to do with the constructors being called outside any methods in the MonoBehavior?

    Code (CSharp):
    1. public class testW3 : MonoBehaviour
    2. {
    3.     TestW3_data testW3_Data;
    4.     int[] int_DataArray;
    5.     TestW3_data[] testW3_DataArray;
    6.     void Start()
    7.     {
    8.         testW3_Data = new TestW3_data();
    9.         int_DataArray = new int[12];
    10.         testW3_DataArray = new TestW3_data[123];
    11.  
    12.         // Your code here
    13. }
    If that solves the problem, I suppose that would be it.
     
  9. JeffDUnity3D

    JeffDUnity3D

    Unity Technologies

    Joined:
    May 2, 2017
    Posts:
    14,446
    Wow, you are correct! Sorry for the confusion, I should ensure to get it right before taking a stand :) At any rate, it's apparently null. I believe we are missing the new() thing
     
    Last edited: Jun 29, 2022
  10. Schneider21

    Schneider21

    Joined:
    Feb 6, 2014
    Posts:
    3,510
    @JeffDUnity3D is it standard to initialize arrays and call object constructors at the class level in MonoBehaviors? Since I do see in the OP's code where they're using the new keyword, I'm not sure why the objects would be null. Could it be something with the serialized instance in Unity having items removed from it in the Inspector, and the class-level stuff doesn't get called again to initialize new instances within the array?

    I don't write code in the same style the OP does, so I can't say I've run into this myself.
     
  11. JeffDUnity3D

    JeffDUnity3D

    Unity Technologies

    Joined:
    May 2, 2017
    Posts:
    14,446
    I'm afraid I'm going to have to pass, the variable names that differ only in their case is too hard to read for me. I was still looking at the code in the original post, sorry.
     
  12. Schneider21

    Schneider21

    Joined:
    Feb 6, 2014
    Posts:
    3,510
    Actually, I think you're right! I didn't notice the original code was missing the new. Since the comments were still there on the second version, I assumed the error still persisted, but the OP does mention figuring it out, though they attributed it to their function that initializes if null.

    @aMIGA_dUDE This is actually a great example of how writing readable code using standard naming conventions can be more valuable than terse or succinct code.

    Another thing I wanted to follow up on that I forgot to mention before:

    This doesn't matter until you're at the level of performance optimization where you're looking to save every frame you can. Generic collections like Lists, Dictionaries, and HashSets are so much easier to work with that it's absolutely worth the minute performance cost for the boost they provide to productivity. Generally the teams I've been on have focused on making it work first, and going back to optimize as needed later. It's almost never been needed to optimize away a List into an array.