我想将ushort数组转换为short数组,而无需在C#内核中分配任何新内存。
还可以将任何类型转换,例如byte []转换为short [],反之亦然-转换需要在内存中为源和目标保持相同的大小
在C语言中有“联合”语法,可以通过多次类型转换来引用该类型-我没有发现C#的任何等效方法(仅适用于非原始类型)。
一种方法是像这样编码
ushort[] res = new ushort[1024 * 1024 * 1024];
short[] s = new short[1024 * 1024 * 1024];
Buffer.BlockCopy(s, 0, res, 0, s.Length * 2);
...但是,我不会分配's'值-它消耗太多内存,并可能导致内存泄漏。
我使用的另一种替代方法是使用不安全模式。
代码:
unsafe
{
ushort[] res = new ushort[1024*1024*1024]; // large allocating
fixed (ushort* ss = &res[0])
{
IntPtr ps = (IntPtr)ss;
short[] s0 = (short[])Marshal.PtrToStructure(ps, typeof(short[]));
}
}
遇到异常。
没有为此对象定义无参数的构造函数。
...
在System.RuntimeTypeHandle.CreateInstance(运行时类型,布尔publicOnly,布尔wrapExceptions,布尔&canBeCached,RuntimeMethodHandleInternal和ctor)
在System.RuntimeType.CreateInstanceSlow(布尔publicOnly,布尔wrapException,布尔skipCheckThis,布尔fillCache)
在System.Runtime.InteropServices.Marshal.PtrToStructure(IntPtr ptr,类型structureType)
我最终如何在不需要分配新内存的情况下转换1G字节的大型数组?
我可以将数组类型从非托管类型转换为托管类型吗?
如果可能的话,我更喜欢使用不安全模式。
经过深入搜索,我找到了一个解决方案,我可以参与(并编辑这篇文章),但是存在如下问题:
如果数组的大小相同,则代码运行得很好-有一个新问题-如何针对非相同的数组基本类型大小(即short [] vs byte [])解决它?
我唯一不能将short []转换为byte []。
在C#核心和C#.NET上都可以使用
首先,创建一个类:
public static class MyConverter
{
public static unsafe T GetInstance<T>(IntPtr pointer)
{
try
{
var fakeInstance = default(T);
TypedReference typedReference = __makeref(fakeInstance);
*(IntPtr*)(&typedReference) = pointer;
T instance = (T) __refvalue(typedReference,T);
return instance;
}
catch
{
return default(T);
}
}
}
并可以在这样的代码中使用它:
ushort[] x = new ushort[1024];
GCHandle handle1 = GCHandle.Alloc(x);
IntPtr px = (IntPtr)handle1;
x[0] = 1;
x[1] = 2;
x[2] = 3;
short[] s = MyConverter.GetInstance<short[]>(px);
该解决方案将ushort []转换为short [],而不会浪费内存。
谢谢。
答案 0 :(得分:-1)
您可以轻松地像这样进行转换:(ushort[])(object)myShortArray
。 CLR允许这样做。
仅允许大小相同的基本数组元素类型。
在其他情况下,您可以使用Span
将内存视为其他类型。
Span<int> asInts = MemoryMarshal.Cast<byte, int>(asBytes);