IntPtr
是struct
,因此默认情况下按值传递,这可能很昂贵(因为每次都会创建新对象),所以当新对象不是时,我们最好通过引用传递它强制性的。例如,我编写了这样的代码(请忽略硬编码的“幻数”):
public static DateTime IntPtrToDateTime(ref IntPtr value, int offset)
{
short year = Marshal.ReadInt16(value, offset);
byte month = Marshal.ReadByte(value, offset + 2);
byte day = Marshal.ReadByte(value, offset + 3);
byte hour = Marshal.ReadByte(value, offset + 4);
byte minute = Marshal.ReadByte(value, offset + 5);
byte second = Marshal.ReadByte(value, offset + 6);
short msec = Marshal.ReadInt16(value, offset + 8);
return new DateTime(year, month, day, hour, minute, second, msec);
}
工作正常,但我怀疑我是否真的应该通过引用传递IntPtr?我猜IntPtr
结构非常“轻”,可能很容易创建。
同样在.NET框架中的Marshal
类中按值传递IntPtr
,例如Marshal.ReadInt64我猜Marshal
类被设计为可能性最小的延迟,但是那么为什么IntPtr
没有通过引用传递?
Marshal
类会按值传递IntPtr
?答案 0 :(得分:1)
结构按值传递,并且没有为它们分配新的堆对象。此外,IntPtr是CLR本身理解的类型。它是单个指针的大小。您应该期望获得与int
或long
相同的性能配置文件(具体取决于您的位数)。
通过引用传递它会减慢速度,因为你用指针包装一个指针。
答案 1 :(得分:1)
不,你不应该通过引用传递它。在这种情况下,这只会导致代码中的更多开销。
因为它是一个指针大小的结构,通过值和引用传递它会在堆栈上放入相同数量的数据,并且将它放在堆栈上的工作量相同。
然后使用通过引用传递的参数将导致另一个间接级别。您将从堆栈中读取指针,然后使用指针读取值,而不是从堆栈中读取值。
此外,对于您实际想要更改用于传递值的变量的参数,您应该只使用ref
或out
。
如果由于性能原因而想要通过引用传递大型结构,那么实际上它本身就是导致性能问题的大型结构,而不是如何将其作为参数传递。你应该把它变成一个类,而不是改变你传递它的方式。