在C#中获取KeyValuePair 数组的不安全指针

我有KeyValuePair大数组KeyValuePair 。 我知道在内存中数组是连续的,因为KVP是一个值类型,DateTime实际上是一个Int64,十进制是一个4个整数的数组(并且不会改变)。 但是,DateTime不是blittable,十进制不是原始的。

没有办法滥用类型系统并获得一个不安全的指针指向数组并使用它作为字节? (当GCHandle.Alloc是结构的一部分时,它们不能与这两种类型一起使用,但对于那些类型的数组可以正常工作。)

(如果你感兴趣的原因,我现在手动将数组转换为我认为是1对1字节[]表示,并且它很慢)

最后,还有一个公共工具: System.Runtime.CompilerServices.Unsafe包。

以下是通过测试:

 using System.Runtime.CompilerServices.Unsafe; [Test] public unsafe void CouldUseNewUnsafePackage() { var dt = new KeyValuePair[2]; dt[0] = new KeyValuePair(DateTime.UtcNow.Date, 123.456M); dt[1] = new KeyValuePair(DateTime.UtcNow.Date.AddDays(1), 789.101M); var obj = (object)dt; byte[] asBytes = Unsafe.As(obj); //Console.WriteLine(asBytes.Length); // prints 2 fixed (byte* ptr = &asBytes[0]) { // reading this: https://github.com/dotnet/coreclr/issues/5870 // it looks like we could fix byte[] and actually KeyValuePair will be fixed // because: // "GC does not care about the exact types, eg if type of local object // reference variable is not compatible with what is actually stored in it, // the GC will still track it fine." for (int i = 0; i < (8 + 16) * 2; i++) { Console.WriteLine(*(ptr + i)); } var firstDate = *(DateTime*)ptr; Assert.AreEqual(DateTime.UtcNow.Date, firstDate); Console.WriteLine(firstDate); var firstDecimal = *(decimal*)(ptr + 8); Assert.AreEqual(123.456M, firstDecimal); Console.WriteLine(firstDecimal); var secondDate = *(DateTime*)(ptr + 8 + 16); Assert.AreEqual(DateTime.UtcNow.Date.AddDays(1), secondDate); Console.WriteLine(secondDate); var secondDecimal = *(decimal*)(ptr + 8 + 16 + 8); Assert.AreEqual(789.101M, secondDecimal); Console.WriteLine(secondDecimal); } } 

我刚刚测试了unsafeGCHandle.Alloc不起作用(正如你的建议)。 还有一个非常不安全的黑客仍然这样做。 我不知道这对当前的CLR是否安全。 当然不能保证将来有效。

您可以将任何类型的对象引用转换为IL中的任何其他引用类型。 IL无法validation。 JIT倾向于接受相当多的不可validation的结构。 也许这是因为他们想要支持Managed C ++。

因此,您需要生成一个大致具有以下IL的DynamicMethod:

 static T UnsafeCast(object value) { ldarg.1 //load type object ret //return type T } 

我觉得这应该有用……

或者,您可以使用Reflection调用System.Runtime.CompilerServices.JitHelpers.UnsafeCast

这是一个危险的工具……我不会在生产代码中使用它。