V.B. V.B. - 3 months ago 19
C# Question

Get unsafe pointer to array of KeyValuePair<DateTime,decimal> in C#

I have big arrays of

KeyValuePair<DateTime,decimal>
. I know that in memory the array is contiguous since KVP is a value type, DateTime is effectively an Int64, and decimal is an array of 4 ints (and that won't change). However, DateTime is not blittable, and decimal is not primitive.

Is there any way to abuse type system and get an unsafe pointer to the array and work with it as bytes? (
GCHandle.Alloc
cannot work with these two types when they are a part of a structure, but works OK with arrays of those type.)

(If you are interested why, I convert the array now manually to what I believe is 1-to-1 byte[] representation, and it is slow)

usr usr
Answer

I just tested that unsafe and GCHandle.Alloc don't work (as you suggested). There is a terribly unsafe hack to still do this. I don't know if this is safe with the current CLR. It certainly is not guaranteed to work in the future.

You can convert an object reference of any type to any other reference type in IL. That IL will not be verifiable. The JIT tends to accept quite a few non-verifiable constructs. Maybe this is because they wanted to support Managed C++.

So you need to generate a DynamicMethod that roughly has the following IL:

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

I think this should work...

Or, you can call System.Runtime.CompilerServices.JitHelpers.UnsafeCast<T> using Reflection.

This is a dangerous tool... I would not use it in production code.