【问题标题】:How to change array reference index with don't use pointer in C#?如何在 C# 中使用不使用指针来更改数组引用索引?
【发布时间】:2019-11-11 18:57:17
【问题描述】:

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

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

下面是我正在写的代码。

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

有没有不使用指针改变引用的方法?

【问题讨论】:

  • 你忘记了你在.net。您的代码“设计”很慢,因为它是托管的。因此,这种微优化可能只会比加速造成更大的伤害。但如果你 100% 确定 - 有一个 ref keyword
  • 我使用了类似“ref &RowData[Marshal.SizeOf(Last.Value)]”和“ref RowData + Marshal.SizeOf(Last.Value)”的 ref,但无法编译。如何使用 ref 关键字?
  • public DatagramPacket(ref byte[] RowData) : base(RowData)
  • 很自然的,我将ref关键字应用到了构造函数的参数上并编译了它。但是,由于与fixed一起使用时出现编译错误,因此无法使用。既然fixed也是不安全的,我觉得和使用指针没什么区别。

标签: c# ethercat


【解决方案1】:

我已经通过复制数组解决了这个问题,如下所示,但我认为它会比以任何方式引用它要慢。我试图实时处理数据包以显示图形,但我应该像使用 .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));
        }
    }
}

【讨论】:

  • 没有定义约束就没有“实时”。选择可行的方法,仅在当前实现导致实际问题时进行优化。而且我不推荐在 C# 中编码thinking ;)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-04-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-10-11
  • 1970-01-01
相关资源
最近更新 更多