如何在C#中不使用指针来更改数组引用索引?

时间:2019-07-01 05:09:08

标签: c# ethercat

我正在编写代码以解析数据包。

我想更改数组的引用地址,但是我不知道如何在不使用指针的情况下更改引用地址。 如果我复制数组的一部分,我认为它会变慢。如果使用指针,那将是不安全的。

下面是我正在编写的代码。

public class Datagrams : LinkedList<DatagramPacket>
{
    public Datagrams(byte[] RowData) : base()
    {
        AddLast(new DatagramPacket(RowData));
        while(Last.Value.header.Length.LastIndicator)
        {
            ///////////////////////////////////////////
            //I want do that. But this is unsafe code//
            ///////////////////////////////////////////
            AddLast(new DatagramPacket( RowData + sizeof[Last.Value] ));
        }
    }
}

public class DatagramPacket : Packet
{
    public enum DatagramCmd : Byte
    {
        NOP = 0x0,
        APRD = 0x1,
        APWR = 0x2,
        APRW = 0x3,
        FPRD = 0x4,
        FPWR = 0x5,
        FPRW = 0x6,
        BRD = 0x7,
        BWR = 0x8,
        BRW = 0x9,
        LRD = 0xA,
        LWR = 0xB,
        LRW = 0xC,
        ARMW = 0xD,
        FRMW = 0xE
    }

    [StructLayout(LayoutKind.Explicit)]
    public struct DatagramAddr
    {
        [MarshalAs(UnmanagedType.U4), FieldOffset(0)]
        public UInt32 LogicalAddr;
        [MarshalAs(UnmanagedType.U2), FieldOffset(0)]
        public UInt16 SlaveAddr;
        [MarshalAs(UnmanagedType.U2), FieldOffset(2)]
        public UInt16 OffsetAddr;
    }

    public struct DatagramLength
    {
        [MarshalAs(UnmanagedType.U2)]
        public UInt16 bits;

        public int Length { get => bits & 0x07FF; }
        public bool Valid { get => (bits & 0x0380) == 0; }
        public bool RoundTrip { get => (bits & 0x4000) != 0; }
        public bool LastIndicator { get => (bits & 0x8000) != 0; }
    }

    [StructLayout(LayoutKind.Sequential, Pack = 1)]
    public struct DatagramHeader
    {
        [MarshalAs(UnmanagedType.U1)]
        public DatagramCmd Cmd;
        [MarshalAs(UnmanagedType.U1)]
        public Byte Index;
        [MarshalAs(UnmanagedType.Struct)]
        public DatagramAddr Addr;
        [MarshalAs(UnmanagedType.Struct)]
        public DatagramLength Length;
        [MarshalAs(UnmanagedType.U2)]
        public UInt16 Interrupt;
    }

    public DatagramHeader header;
    public UInt16 wc;  //Working Count

    public DatagramPacket(byte[] RowData) : base(RowData)
    {
        header = new DatagramHeader();
        GCHandle handle = GCHandle.Alloc(RowData, GCHandleType.Pinned);
        try
        {
            header = (DatagramHeader)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(DatagramHeader));
        }
        finally
        {
            handle.Free();
        }
        body = new byte[header.Length.Length];
        Buffer.BlockCopy(RowData, Marshal.SizeOf<DatagramHeader>(), body, 0, body.Length);
        wc = BitConverter.ToUInt16(RowData, Marshal.SizeOf<DatagramHeader>() + body.Length);
    }

    public override Packet Parse()
    {
        throw new NotImplementedException();
    }
}

有没有不用指针就可以更改引用的方法吗?

1 个答案:

答案 0 :(得分:0)

我已经通过复制数组来解决问题,如下所示,但是我认为它比通过任何方式引用它都要慢。我试图实时处理数据包以显示图形,但是我应该放弃使用.net所进行的实时处理吗?

 public class Datagrams : LinkedList<DatagramPacket>
{
    public Datagrams(byte[] RowData) : base()
    {
        AddLast(new DatagramPacket(RowData));
        while(Last.Value.header.Length.LastIndicator)
        {
            int index = Marshal.SizeOf<DatagramPacket.DatagramHeader>() + Last.Value.header.Length.Length + sizeof(UInt16);
            byte[] temp = new byte[RowData.Length - index];
            Buffer.BlockCopy(RowData, index, temp, 0, RowData.Length - index);
            RowData = temp;
            AddLast(new DatagramPacket(RowData));
        }
    }
}