Gri*_*ios 7 c# arrays reinterpret-cast
我正在使用 C# (.NET 5)。想象一下,我有一个存储结构数组(例如浮点数)的类:
public class StoresArray
{
private float[] floats;
}
Run Code Online (Sandbox Code Playgroud)
此类的数据是从序列化的二进制文件加载的。为了分配floats数组,我使用辅助函数从序列化文件中读取字节。重要的是,此函数然后尝试直接将加载的字节重新解释为而不是复制到新数组。float[]
public static class Deserializer
{
public static float[] Load(string file)
{
byte[] bytes = LoadBytesFromFile(file);
// This is a compiler error, of course.
return (float[])bytes;
}
}
Run Code Online (Sandbox Code Playgroud)
预期用途如下:
// Within the StoresArray class...
floats = Deserializer.Load("MyFile.file");
Run Code Online (Sandbox Code Playgroud)
这里值得注意的是,我试图将存储float[]为成员变量,而不仅仅是在byte[]本地迭代。因此,通过Span<T>( Span<float> floatSpan = MemoryMarshal.Cast<byte, float>(bytes.AsSpan())) 进行投射是不够的。Memory<T>与、Marshal、 和相关的功能MemoryMarshal也同样失败。当然,我可以使用跨度(以及其他方法,如或不安全的指针)从BitConverter构建一个新 的,但这会产生额外的数组分配,以及转换字节的额外操作。在我要求的上下文中(动态加载视频游戏资源),我想尽可能优化性能。float[]byte[]
在现代 C# 中,是否可以重新解释和存储结构数组而不产生额外的分配?
要写,你可以这样做:
public static void WriteArrayToStream<T>(Stream output, T[] array) where T: unmanaged
{
var span = array.AsSpan();
var bytes = MemoryMarshal.AsBytes(span);
output.Write(bytes);
}
Run Code Online (Sandbox Code Playgroud)
为了阅读,你可以这样做:
public static (T[] Result, int Count) ReadArrayFromStream<T>(Stream input, int n) where T: unmanaged
{
T[] result = new T[n];
var span = result.AsSpan();
var bytes = MemoryMarshal.AsBytes(span);
int count = input.Read(bytes);
return (result, count/Marshal.SizeOf<T>());
}
Run Code Online (Sandbox Code Playgroud)
请注意,它返回一个元组,因为如果没有足够的数据可用,则只有第一个Count元素具有有效数据。
这是一个显示写入和读取double[]数组的示例:
MemoryStream mem = new MemoryStream();
double[] data = Enumerable.Range(0, 100).Select(x => (double)x).ToArray();
WriteArrayToStream(mem, data);
Console.WriteLine(mem.Length); // 800
mem.Position = 0;
var (array, count) = ReadArrayFromStream<double>(mem, 200);
Console.WriteLine(count); // 100
Console.WriteLine(array[42]); // 42
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1698 次 |
| 最近记录: |