我正在尝试创建一个属性,它将从我的字节数组(byte [])中生成一个指针(byte *),这确实有效,但每当我修改这个返回的指针时,我的字节数组都不会被修改,这个是我想要使用的代码片段。
public unsafe class PacketWriter
{
private readonly byte[] _packet;
private int _position;
public byte* Pointer
{
get
{
fixed (byte* pointer = _packet)
return pointer;
}
}
public PacketWriter(int packetLength)
{
_packet = new byte[packetLength];
}
//An example function
public void WriteInt16(short value)
{
if (value > Int16.MaxValue)
throw new Exception("PacketWriter: You cannot write " + value + " to a Int16.");
*((short*)(Pointer + _position)) = (short) value;
_position += 2;
}
//I would call this function to get the array.
public byte[] GetPacket
{
get { return _packet; }
}
}
另外,我意识到我可以简单地删除属性并将代码放在函数中,这可能会起作用,但是我试图找出使用该属性的方法 - 除非这会降低性能,在这种情况下请告诉我。
答案 0 :(得分:6)
在这里使用指针(在C#中)毫无意义。
请注意,如果使用
替换Pointer
属性
public byte[] Data { get { return _packet; } }
您有一个属性可以将引用返回给字节数组,它可以让您在数组中作为指针进行相同的编辑,而无需在任何时候复制数组。
在Write16中,另一条建议使用:
byte[] data = BitConverter.GetBytes(value);
data.CopyTo(_packet, _positiion);
_position += data.Length;
答案 1 :(得分:2)
当你的控件离开fixed
时(它在返回后立即执行)你的对象不再被固定。因此它仅在fixed
答案 2 :(得分:2)
不要暴露指针。 您可以先发制人地优化代码。 举个例子,我在C#中编写了一个PNG解码器,用于我正在研究的项目,而不是假设瓶颈,我编写代码使管理数据结构变得微不足道,并且对I / O和数据移动相当轻松。在对代码进行基准测试时,瓶颈不在数据移动或I / O中,而是在Paeth预测器中 - 计算是基于每个像素进行的(详细信息here)。
首先编写可读和可维护的代码,然后查看瓶颈所在。你以后总是可以重构它。
答案 3 :(得分:1)
在.NET中索引到数组是非常有效的;抖动生成的机器代码基本上等同于通过指针算法进行访问。如果您编写使用位掩码并移位以生成用于写入数组的字节值的等效代码,则可能比不安全代码的尝试更快。固定的开销远远高于一些廉价的位掩码操作。
如果你真的,绝对需要节省几个时钟周期(以降低可维护性的昂贵代价),要么在C ++中创建一个非托管DLL来处理高性能要求,要么编写完全在非托管内存上运行的纯不安全代码元帅。事实上,Marshal已经有了WriteInt16方法可以使用。然而,编组回管理内存的开销会相对较高(远高于位掩码),所以只有在非常内循环中编写大量内存并且正在执行其他操作时,这才有用。除了简单复制之外的操作(因为无论如何它都必须复制到托管内存以进行编组)。
答案 4 :(得分:0)
如果您正在处理托管内存,那么是的,您必须将其限制为fixed
块。
看来你似乎在使用大量的指针处理,我的问题是为什么你需要一个托管内存?只需使用Marshal.AllocHGlobal()
分配一些非托管内存,然后将其作为指针公开。您只需要确保在Dispose()
中发布它。