I'm looking for a semi-general purpose data structure in C# to store arrays of different integer and float types. In some cases, the integers are bit fields where each bit is equally important and loss of precision isn't tolerable. I'm finding this difficult and messy because of the C# type system and my lack of C# fluency.
The project: Ethercat periodic packets arrive and are converted to a structure (Packet) and accumulated as Packet[]
over the course of an experiment. Each field of Packet from Packet[]
is converted into an array.
I believe I'm looking for a way to 'wrap' these arrays into a single type so they can be part of a collection. Wrapping them has some other advantages (naming, hardware to SI scale factors, etc) to facilitate decoupling the hardware from the later implementation.
My best 'wrapper' is called 'DataWrapper' (simplified below) but with it I've made uncomfortable compromises in storage, loss of precision, use of object and quantity of code.
Is there a 'better' way in C#? My gold standard is the apparently trivial implementation without obvious compromises in Python using list of lists or numpy.arrays.
Could 'object' be used? How? Is it possible to box the whole array or must each array element boxed individually (inefficient)?
I've seen A list of multiple data types? however, seems like a lot of code and advanced programming techniques for what is essentially a List of List.
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));
}
}