c# - 实现不同类型数组集合的更好方法

标签 c# data-structures collections type-systems typed-arrays

我正在寻找 C# 中的半通用数据结构来存储不同整数和浮点类型的数组。在某些情况下,整数是位字段,其中每一位都同等重要,并且不能容忍精度损失。由于 C# 类型系统和我缺乏 C# 流畅性,我发现这很困难和困惑。

项目:Ethercat 周期性数据包到达并转换为结构 (Packet),并在实验过程中累积为 Packet[]Packet[] 中的 Packet 的每个字段都被转换成一个数组。

我相信我正在寻找一种方法将这些数组“包装”成单一类型,以便它们可以成为集合的一部分。包装它们还有一些其他优势(命名、硬件到 SI 比例因子等),以便于将硬件与以后的实现解耦。

我最好的“包装器”称为“DataWrapper”(在下面进行了简化),但我在存储、精度损失、对象使用和代码数量方面做出了令人不安的妥协。

在 C# 中有“更好”的方法吗?我的黄金标准是在 Python 中使用列表列表或 numpy.arrays 的明显微不足道的实现,没有明显的妥协。

可以使用“object”吗?如何?是否可以装箱整个数组或必须单独装箱每个数组元素(效率低下)?

我看过 A list of multiple data types?但是,对于本质上是列表列表的内容,似乎有很多代码和高级编程技术。

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));  
    }
}

最佳答案

您可以将其视为 byte[] 列表并使用 BitConverter 将值类型序列化以将值类型转换为 byte[],然后使用反向调用展开它;

List<byte[]> dataList = new List<byte[]>();
float v = 1.0424f;
byte[] converted = BitConverter.GetBytes(v);
// put converted into a List<byte[]> 
dataList.Add(converted);
// Convert it back again
float z= BitConverter.ToSingle(dataList[0], 0);

关于c# - 实现不同类型数组集合的更好方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39798481/

相关文章:

c# - 结合两个不同类型的序列

C# - 第二个参数等于字符串长度的字符串 IndexOf 方法

python - 嗨,将 python 中的值设置为列表中的任何索引的更 pythonic 方法是什么?

algorithm - 斯卡拉 : Sorting list of number based on another list

algorithm - 如何用一个数组实现 3 个堆栈?

c# - 在 C# 中,将接口(interface)列表转换为对象列表的推荐方法是什么?

c# - C# 集合是值类型还是引用类型?

c# - 无法使用 iTextSharp 应用样式

c# - 实现 MS Access 样式 'relationships' GUI

c# - 如何根据小数位数获取整数的动态最大值