Я ищу полууниверсальную структуру данных на С# для хранения массивов различных целых и плавающих типов. В некоторых случаях целые числа представляют собой битовые поля, где каждый бит одинаково важен, и потеря точности недопустима. Я нахожу это сложным и запутанным из-за системы типов С# и отсутствия свободного владения языком С#.
Проект: периодические пакеты Ethercat прибывают, преобразуются в структуру (пакет) и накапливаются как Packet[]
в ходе эксперимента. Каждое поле пакета из Packet[]
преобразуется в массив.
Я считаю, что ищу способ «обернуть» эти массивы в один тип, чтобы они могли быть частью коллекции. Их обертывание имеет некоторые другие преимущества (именование, аппаратные коэффициенты масштабирования SI и т. Д.), Чтобы облегчить отделение аппаратного обеспечения от более поздней реализации.
Моя лучшая «обертка» называется «DataWrapper» (упрощенно ниже), но с ней я пошел на неудобные компромиссы в хранении, потере точности, использовании объекта и количестве кода.
Есть ли «лучший» способ в С#? Мой золотой стандарт — очевидно тривиальная реализация без очевидных компромиссов в Python с использованием списка списков или numpy.arrays.
Можно ли использовать «объект»? Как? Можно ли упаковать весь массив или каждый элемент массива должен быть упакован отдельно (неэффективно)?
Я видел список нескольких типов данных? однако это похоже на много кода и передовых методов программирования для того, что по сути является списком списка.
public class DataWrapper
{
private double[] double_array; // backing with double, but it could if I don't use float
private string name;
private double scale_factor_to_SI;
public DataWrapper(string name, double scale_factor, dynamic dynamic_array)
{
this.name = name;
this.scale_factor_to_SI = scale_factor;
this.double_array = new double[dynamic_array.Length];
for (int cnt = 0; cnt < dynamic_array.Length; cnt++)
{
this.double_array[cnt] = (double)dynamic_array[cnt];
}
}
public void Get(out int[] i_array)
{
i_array = this.double_array.Select(item => (int)item).ToArray();
}
public void Get(out long[] i_array)
{
i_array = this.double_array.Select(item => (long)item).ToArray();
}
public double[] GetSI()
{
return this.double_array.Select(item => this.scale_factor_to_SI * (double)item).ToArray();
}
}
public struct Packet // this is an example packet - the actual packet is much larger and will change over time. I wish to make the change in 1 place not many.
{
public long time_uS;
public Int16 velocity;
public UInt32 status_word;
};
public class example
{
public Packet[] GetArrayofPacketFromHardware()
{
return null;
}
public example() {
Packet[] array_of_packet = GetArrayofPacketFromHardware();
var time_uS = array_of_packet.Select(p => p.time_uS).ToArray();
var velocity = array_of_packet.Select(p => p.velocity).ToArray();
var status_bits = array_of_packet.Select(p => p.status_word).ToArray();
List<DataWrapper> collection = new List<DataWrapper> { };
collection.Add(new DataWrapper("time", 1.0e-6, time_uS));
collection.Add(new DataWrapper("velocity", 1/8192, velocity));
collection.Add(new DataWrapper("status", 1, status_bits));
}
}
List<T>
, гдеT
— это класс, который имеет int, double и float, а также поле типа, указывающее, какой из них используется. Обычно у меня было простоobject
и поле типа, но вы упомянули накладные расходы на распаковку. Это проблема, которую вы никогда не сможете решить очень чисто на языке со строгой типизацией, таком как C#. Самое чистое, что вы можете получить для его потребления, это тип шаблона посетителя для итерации по коллекции. Тогда вы могли бы, по крайней мере, избежать переключения в поле типа. ПОМОЩЬ. - person 15ee8f99-57ff-4f92-890c-b56153   schedule 30.09.2016