好的基本思路是我要做的是将字节数组转换为short或int等等。
一个简单的例子可能是:
unsafe
{
fixed (byte* byteArray = new byte[5] { 255, 255, 255, 126, 34 })
{
short shortSingle = *(short*)byteArray;
MessageBox.Show((shortSingle).ToString()); // works fine output is -1
}
}
好的,我真正想做的是,对Stream类进行扩展;扩展的读写方法。我需要以下代码的帮助:
unsafe public static T Read<T>(this Stream stream)
{
int bytesToRead = sizeof(T); // ERROR: Cannot take the address of, get the size of, or declare a pointer to a managed type ('T')
byte[] buffer = new byte[bytesToRead];
if (bytesToRead != stream.Read(buffer, 0, bytesToRead))
{
throw new Exception();
}
fixed (byte* byteArray = buffer)
{
T typeSingle = *(T*)byteArray; // ERROR: Cannot take the address of, get the size of, or declare a pointer to a managed type ('T')
return typeSingle;
}
}
unsafe public static T[] Read<T>(this Stream stream, int count)
{
// haven't figured out it yet. This is where I read and return T arrays
}
我觉得我必须使用指针来提高速度,因为我将致力于从NetworkStream类等流中编写和读取数据。谢谢你的帮助!
编辑:
虽然我试图弄清楚如何返回T阵列,但我遇到了这个问题:
unsafe
{
fixed (byte* byteArray = new byte[5] { 0, 0, 255, 255, 34 })
{
short* shortArray = (short*)byteArray;
MessageBox.Show((shortArray[0]).ToString()); // works fine output is 0
MessageBox.Show((shortArray[1]).ToString()); // works fine output is -1
short[] managedShortArray = new short[2];
managedShortArray = shortArray; // The problem is, How may I convert pointer to a managed short array? ERROR: Cannot implicitly convert type 'short*' to 'short[]'
}
}
摘要: 我必须从字节数组转换为给定类型的T 要么 给定长度的给定类型的T数组
答案 0 :(得分:5)
由于C#中的指针限制,您无法使此函数成为通用函数。以下任何类型都可以是指针类型:
但您无法对T where T <can be pointer type>
设置限制。 where T : struct
非常接近,但还不够,因为用户定义的结构可以包含引用类型的字段。
有一种解决方法 - System.Runtime.InteropServices.Marshal.PtrToStructure()
(如果无法使用指定的对象类型,它只会引发异常),但它也会导致任何已实现的性能改进。
我认为唯一的方法是为所有需要的类型创建非泛型函数。
答案 1 :(得分:1)
修改:unmanaged
constraint已添加到C# 7.3。
在这个问题上稍稍跳了一下,但是在C#7.3中增加了unmanaged
类型约束。
使用非托管类型约束,您可以使用通用指针(T*
)等,只要传入的类型是非托管的。
我测试了你提供的通用方法,现在它确实有效。此外,您可以扩展它以返回如下所示的数组:
public static unsafe T[] ReadAsArray<T>(this Stream stream) where T : unmanaged
{
var length = stream.Length;
var returnArray = new T[length];
for (var i = 0; i < length; i++)
{
int bytesToRead = sizeof(T); // no longer throws error
byte[] buffer = new byte[bytesToRead];
if (bytesToRead != stream.Read(buffer, 0, bytesToRead))
{
throw new Exception();
}
fixed (byte* byteArray = buffer)
{
T typeSingle = *(T*)byteArray; // no longer throws error
returnArray[i] = typeSingle;
}
}
return returnArray;
}
您可以使用以下代码调用它,该代码将打印文件的内容:
using (var sourceStream = File.Open(filename, FileMode.Open))
{
var byteArray = sourceStream.ReadAsArray<byte>();
Console.Write(new string(byteArray.Select(b => (char)b).ToArray()));
}