R Read Ответов: 3

У меня есть проблема с добавлением данных байтового массива в буфер списка<byte[]> с помощью цикла while


У меня есть поток байтов данных, который состоит из нескольких сообщений данных. Я читаю данные и использую государственную машину, чтобы разбить данные на отдельные сообщения. Каждое сообщение sepeate хранится в байтовом массиве bData[250]. Прежде чем перейти к декодированию следующего сообщения, я помещаю предыдущее декодированное сообщение в буфер списка " byte []", а затем повторно использую массив байтов bData для декодирования следующего сообщения и затем добавляю его в буфер списка.
Проблема, с которой я сталкиваюсь, заключается в том, что Buffer.Add() работает вне моего цикла while, но не в нем. Внутри цикла все элементы списка имеют те же данные, что и последний добавленный элемент.
Я разбил проблему на вызов простой функции, где я могу отобразить проблему, но, к сожалению, не решить ее! Ниже приведена моя простая функция тестирования/отладки:
byte[] requestToolDataMsg = new byte[] { 0x4B, 0x01, 0x00, 0x00, 0xB4 };
byte[] requestTest = new byte[] { 0x4B, 0x16, 0x00, 0x00, B4 };
byte[] clientTableReadMsg = new byte[] { 0x4B, 0x00, 0x27,
0x5A, 0x01, 0x02, 0x16, 0x04, 0x0A, 0x0B, 0x0C, 0x0D, 0x00, 0x00, 0xA5,
0x5A, 0x01, 0x02, 0x17, 0x05, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x00, 0x00, 0xA5,
0x5A, 0x01, 0x02, 0x18, 0x06, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x00, 0x00, 0xA5,
0xB4 };

static List<byte[]> buffer = new List<byte[]>();

private void UdateList()
{
	byte[] bData = new byte[256];
	int kk = 0;

	buffer.Add(requestToolDataMsg);
	buffer.Add(clientTableReadMsg);
	buffer.Clear();
	while (kk < 3)
	{
		kk++;
		requestToolDataMsg[0] = (byte)kk;
		buffer.Add(requestToolDataMsg);
	}
}

Вне буфера цикла while.Add() работает. В первый раз внутри цикла while добавляются правильные данные, но во второй раз через цикл данные верны для второго элемента, но они также перезаписывают первый элемент. После третьего раза через цикл все 3 элемента имеют значение третьего элемента.

то есть я получаю:
0x03, 0x01, 0x00, 0x00, 0xB4
0x03, 0x01, 0x00, 0x00, 0xB4
0x03, 0x01, 0x00, 0x00, 0xB4

вместо:
0x01, 0x01, 0x00, 0x00, 0xB4
0x02, 0x01, 0x00, 0x00, 0xB4
0x03, 0x01, 0x00, 0x00, 0xB4


Что я уже пробовал:

Я пытался определить список буферов "байт []" внутри функции и вне функции, но это не помогает (хватаясь за соломинку здесь. Я получаю ту же проблему с целочисленными списками, но работает, если я использую списки строковых массивов

3 Ответов

Рейтинг:
25

Graeme_Grant

Вы добавляете ссылку на массив. Вам нужно сначала скопировать массив, прежде чем изменять и добавлять его в список. Вы могли бы сделать что-то вроде этого:

while (kk < 3)
{
    kk++;
    var copy = new byte[bData.Length];
    Array.Copy(bData, copy, bData.Length);
    copy[0] = (byte)kk;
    buffer.Add(copy);
}


Рейтинг:
19

OriginalGriff

Это происходит потому, что вы добавляете один и тот же буфер каждый раз вокруг цикла: поэтому, когда вы изменяете его в цикле для второго экземпляра, вы изменяете и первый экземпляр.

Массив чего - либо является ссылочным типом-это означает, что он создается в куче, и вы получаете ссылку на этот объект кучи. Когда вы создаете List<byte[]> он содержит ссылки на массивы байтов, а не на содержимое массива значений. Поэтому каждый раз, когда вы вызываете Add, вы помещаете одну и ту же ссылку в список и изменяете ее.
Что вам нужно сделать это добавить новый массив байтов каждый раз:

while (kk < 3)
    {
    kk++;
    byte[] requestToolDataMsg = new byte[] { 0x4B, 0x01, 0x00, 0x00, 0xB4 };
    requestToolDataMsg[0] = (byte)kk;
    buffer.Add(requestToolDataMsg);
    }
Но почему вы добавляете два элемента в список вне цикла, а затем опустошаете список, в который только что их поместили?


Рейтинг:
1

Patrice T

Существует инструмент, который позволяет вам видеть, что делает ваш код, его имя отладчик Это также отличный инструмент обучения, потому что он показывает вам реальность, и вы можете увидеть, какие ожидания соответствуют реальности.
Когда вы не понимаете, что делает ваш код или почему он делает то, что делает, ответ таков: отладчик.
Используйте отладчик, чтобы увидеть, что делает ваш код. Просто установите точку останова и посмотрите, как работает ваш код, отладчик позволит вам выполнять строки 1 на 1 и проверять переменные по мере их выполнения.

Отладчик-Википедия, свободная энциклопедия[^]
Отладка кода C# в Visual Studio-YouTube[^]
Отладчик здесь для того, чтобы показать вам, что делает ваш код, и ваша задача-сравнить его с тем, что он должен делать.
В отладчике нет никакой магии, он не находит ошибок, он просто помогает вам. Когда код не делает того, что ожидается, вы близки к ошибке.