获取不安全的指向数组的KeyValuePair< DateTime,decimal>在C# [英] Get unsafe pointer to array of KeyValuePair<DateTime,decimal> in C#

查看:139
本文介绍了获取不安全的指向数组的KeyValuePair< DateTime,decimal>在C#的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

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.

是否有 滥用类型系统并获得一个不安全的数组指针,并以字节为单位? ( GCHandle.Alloc 在这些类型的一部分时不能与这两种类型一起使用,但可以使用这些类型的数组)。

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.)

(如果你有兴趣为什么,我现在手动转换阵列到我认为是1到1字节[]表示,而且是慢)

(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)

推荐答案

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

Finally, there is a public tool: System.Runtime.CompilerServices.Unsafe package.

以下是一个通过测试:

using System.Runtime.CompilerServices.Unsafe;
[Test]
public unsafe void CouldUseNewUnsafePackage() {
    var dt = new KeyValuePair<DateTime, decimal>[2];
    dt[0] = new KeyValuePair<DateTime, decimal>(DateTime.UtcNow.Date, 123.456M);
    dt[1] = new KeyValuePair<DateTime, decimal>(DateTime.UtcNow.Date.AddDays(1), 789.101M);
    var obj = (object)dt;
    byte[] asBytes = Unsafe.As<byte[]>(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<DateTime, decimal> will be fixed
        // because:
        // "GC does not care about the exact types, e.g. 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);
    }
}

这篇关于获取不安全的指向数组的KeyValuePair&lt; DateTime,decimal&gt;在C#的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆