当我发现unmanaged泛型约束时,我非常兴奋,因为我认为这将解决我的序列化需求。但是,阅读更多关于它的信息,似乎使用约束进行序列化并不是一个好主意。
对于上下文,我正在创建一个低级的网络库,我希望允许用户轻松地序列化简单的类型,比如原语或枚举。我创建了一个接受任何unmanaged类型并将其写入字节数组的泛型方法。
public unsafe void Write<T>(T value, int offset) where T : unmanaged
{
fixed (byte* pointer = &Bytes[offset])
{
*(T*) pointer = value;
}
}阅读同样简单:
public unsafe T Read<T>(int offset) where T : unmanaged
{
fixed (byte* pointer = &Bytes[offset])
{
return *(T*) pointer;
}
}乍一看,这些方法非常适合序列化;它们非常快(简单的直接内存写入或读取),它们是通用的(不需要为每个原语(如int、float等)编写方法)。它们甚至支持用户自定义类型(枚举和自定义unmanaged结构)。
但像往常一样,当某件事看起来太好而不是真的时,通常是这样的。第一个问题是,如果两个系统使用不同的endianness,这些方法就无法工作。例如,system 1写入一个整数,通过网络发送它,系统2(具有不同的endianness)尝试读取它。系统2将解释一个错误的值。
第二个潜在问题是结构布局,不同的平台可能有不同的结构内存布局,因此我们有与endianness相同的问题。
这让我怀疑,在所有平台上都能工作的通用序列化,无论是endianness还是struct布局,是否都是可能的。如果是这样的话,我很想看看解决办法。或者是最好的(也是唯一的)解决方案,分别为每种类型编写序列化方法,如BitConverter、BinaryWriter、BinaryReader和相对较新的BinaryPrimitives。
发布于 2022-06-25 14:27:45
是的,如果您小心的话,您可以使用这个特性在某些情况下加快代码的速度。
[StructLayout(LayoutKind.Sequential, Pack=...)] (或其他语言中的等效语言)实现相应的类型。BinaryPrimitives.ReverseEndianness)。作为自定义二进制协议的维护者,我建议您不要发明自己的协议。这很难,而且容易出错。
就拿阿夫罗或MessagePack来说吧--它们太棒了。
https://stackoverflow.com/questions/72753361
复制相似问题