gpt4 book ai didi

c# - 在 C# 7.3 中序列化非托管泛型类型

转载 作者:太空宇宙 更新时间:2023-11-03 12:14:33 26 4
gpt4 key购买 nike

非托管关键字 added to C# 7.3主要是为互操作而设计的。但它也是said这可能有助于通用序列化方法。同样,this answer展示了这可能如何完成的一部分——特别是反序列化非托管元素数组。

我想知道这样做是否安全。至少有两个问题。首先,根据我的实验,似乎 sizeof(T) 运算符仍然必须在不安全的上下文中使用,即使 T : unmanaged 约束适用。这似乎与以下命题一致,即即使有非托管约束,不同的平台也可能以不同方式布置非托管结构(除非,例如,使用 LayoutKind.Sequential),因此 sizeof 对于序列化目的是不可靠的,as was the case before .当然,我们必须使用不安全上下文来获取通用 T 下的字节。

其次,数字类型在不同的平台上也可能有不同的布局。因此,使用 Span 的 Microsoft 代码包括专门以指定字节顺序读取/写入的方法,例如 here .如果我们在一个平台上序列化一个非托管 T 并在另一个平台上反序列化,那么似乎存在我们将返回具有不同字节顺序的数字的风险。

然后,我的结论是,简单地序列化 T 的底层字节是不安全的,除非有人保证反序列化将在同一平台上进行。对吗?

假设是这样,相关的问题是我们如何仍然可以一般地序列化非托管 T。据推测,我们可以使用 T 上的反射来确定使用了哪些类型,然后我们可以确定 T using unsafe code 的布局。 .然后,考虑到当前系统是小端还是大端,应该可以设计一个算法来序列化和反序列化一个通用的非托管 T。这是正确的吗? (当然,如果有人这样做了,那就太理想了。)

最佳答案

blog postassociated code说明如何序列化和反序列化声明为非托管的结构。一种序列化方法如下:

public static void Write<T>(this Stream stream, T value)
where T : unmanaged
{
var tSpan = MemoryMarshal.CreateSpan(ref value, 1);
var span = MemoryMarshal.AsBytes(tSpan);
stream.Write(span);
}

对应的反序列化代码为:

public static T Read<T>(this Stream stream)
where T : unmanaged
{
var result = default(T);
var tSpan = MemoryMarshal.CreateSpan(ref result, 1);
var span = MemoryMarshal.AsBytes(tSpan);
stream.Read(span);
return result;
}

正如预期的那样,这会产生可观的速度提升,如博文中所述。因此,当数据存储为非托管类型的 Span 时,这可能是一种有用的序列化技术。但是,该技术确实假设值在与序列化平台具有相同字节顺序的平台上被反序列化。对于某些应用程序,考虑到小端机器的主导地位,这不太可能成为问题。如果这是一个问题,可以检查大端机器,然后 convert values序列化之前和反序列化之后。

关于c# - 在 C# 7.3 中序列化非托管泛型类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50414362/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com