Получаю null при вызове массива пользовательского типа, объявленного в классе C#

Рейтинг: 0Ответов: 1Опубликовано: 21.01.2023

Хочу создать тип данных, на основании его создать массив и потом в него закинуть данные, так вот:

  1. Объявляю свой тип:

    public class TIntelHexData {
        public byte type;
        public ushort halfAddress;
        public byte[] data = new byte[16];
    }
    
  2. Создаю класс, где на основании созданного типа создаю массив, изначально не выделял память под него.

    public class IntelHexHandler
    {
        private TIntelHexData[] dataSendBuff = new TIntelHexData[2000];//buffer 
        private byte typeOfMessageHex; //тип строки intel hex
        private byte longOfMessageHex; //длина строки intel hex
    
        public void IntelHexSort(ref byte[] buff)//файл
        {
        }
        public void IntelHexSendBlock(byte size, ref SerialPort port)
        {
        }
    }
    
  3. Создаю экземпляр класса и вызываю внутренние методы:

    private async void Send_to_Flash_btn_ClickAsunc(object sender, EventArgs e)//кнопка
    {
        IntelHexHandler intelHexHandler = new IntelHexHandler();
        await WaitingBeforeNextOperationAsync();//ждем флага выполнения операции
        intelHexHandler.IntelHexSort(ref dataBuffHex);
        intelHexHandler.IntelHexSendBlock(16, ref serialPort1);
    }
    
  4. Как только происходит присваивание внутри класса в массив, получаю NullReferenceException, что я делаю не так? Показан кусок из метода.

    if (CRCcalculated == CRCget)//если чек суммы равны
    {
        dataSendBuff[counter].halfAddress = addressLSB;//ошибка null
    
        for (byte t = 0; t < temp_buff2.Length - 2; t++)
        {
            dataSendBuff[counter].data[t] = temp_buff2[t];
        }
    
        dataSendBuff[counter].type = (byte)Protocol_Id.FirmBody_DATA; 
        counter++;
        //сохраняем младший адрес и данные прошивки intel hex
    }
    else
    {
        /*Ошибка по crc*/
    }
    

Ответы

▲ 2Принят

Всё правильно, экземпляр класса кто будет создавать? Сам он магичнским образом не появится.

if (CRCcalculated == CRCget)
{
    dataSendBuff[counter] = new TIntelHexData();
    dataSendBuff[counter].halfAddress = addressLSB;
    // здесь надо быть внимательным. Если temp_buff2.Length - 2 будет больше 16, вы получите исключение. Потому что new byte[16]
    // в этом случае массив лучше создавать здесь, а не в классе TIntelHexData. Длина же известна
    for (byte t = 0; t < temp_buff2.Length - 2; t++)
    {
        dataSendBuff[counter].data[t] = temp_buff2[t];
    }

    dataSendBuff[counter].type = (byte)Protocol_Id.FirmBody_DATA; 
    counter++;
}
else
{
    /*Ошибка по crc*/
}

Второй вариант решения использовать не класс, а структуру, то есть значимый тип, который не может быть null

public struct TIntelHexData
{
    public byte type;
    public ushort halfAddress;
    public byte[] data;
}

Тогда ваш код отработает без вызова конструктора, но придется массив data создавать в коде, либо реализовывать полноценный конструктор структуры, где инициализируются все её поля.

if (CRCcalculated == CRCget)
{
    dataSendBuff[counter].halfAddress = addressLSB;
    int length = temp_buff2.Length - 2:
    dataSendBuff[counter].data = new byte[length];
    for (byte t = 0; t < length; t++)
    {
        dataSendBuff[counter].data[t] = temp_buff2[t];
    }

    dataSendBuff[counter].type = (byte)Protocol_Id.FirmBody_DATA; 
    counter++;
}
else
{
    /*Ошибка по crc*/
}