在c#中将Guid转换为2个长整型,并将2个长整型转换为Guid

Jea*_*ean 3 .net c# .net-core

Guid是一个128bits的结构,long是一个Int64所以64位的结构,因此Guid可以用来表示两个long,并且两个long可以存储在一个Guid中。

我一直在寻找一种可靠的方法来执行 Guid 到 2 long 的转换以及周围的方法,主要是为了获得一种向外部服务提供跟踪 id 的简单方法。

目标是获得一种可逆的方式来传递单个参数 2 个长整型,并稍后将其解码回来(当然,它不打算在另一端“解码”使用)。它就像外部服务的会话 ID。

Jea*_*ean 5

警告:这些解决方案没有考虑字节顺序,因此结果可能因平台而异

利用C# 7的新功能,我推出了以下工具类,它将long、ulong、int、uint转换为Guid并反转:

public static class GuidTools
{
    public static Guid GuidFromLongs(long a, long b)
    {
        byte[] guidData = new byte[16];
        Array.Copy(BitConverter.GetBytes(a), guidData, 8);
        Array.Copy(BitConverter.GetBytes(b), 0, guidData, 8, 8);
        return new Guid(guidData);
    }

    public static (long, long) ToLongs(this Guid guid)
    {
        var bytes = guid.ToByteArray();
        var long1 = BitConverter.ToInt64(bytes, 0);
        var long2 = BitConverter.ToInt64(bytes, 8);
        return (long1, long2);
    }

    public static Guid GuidFromULongs(ulong a, ulong b)
    {
        byte[] guidData = new byte[16];
        Array.Copy(BitConverter.GetBytes(a), guidData, 8);
        Array.Copy(BitConverter.GetBytes(b), 0, guidData, 8, 8);
        return new Guid(guidData);
    }

    public static (ulong, ulong) ToULongs(this Guid guid)
    {
        var bytes = guid.ToByteArray();
        var ulong1 = BitConverter.ToUInt64(bytes, 0);
        var ulong2 = BitConverter.ToUInt64(bytes, 8);
        return (ulong1, ulong2);
    }

    public static Guid GuidFromInts(int a, int b, int c, int d)
    {
        byte[] guidData = new byte[16];
        Array.Copy(BitConverter.GetBytes(a), guidData, 4);
        Array.Copy(BitConverter.GetBytes(b), 0, guidData, 4, 4);
        Array.Copy(BitConverter.GetBytes(c), 0, guidData, 8, 4);
        Array.Copy(BitConverter.GetBytes(d), 0, guidData, 12, 4);
        return new Guid(guidData);
    }

    public static (int, int , int, int) ToInts(this Guid guid)
    {
        var bytes = guid.ToByteArray();
        var a = BitConverter.ToInt32(bytes, 0);
        var b = BitConverter.ToInt32(bytes, 4);
        var c = BitConverter.ToInt32(bytes, 8);
        var d = BitConverter.ToInt32(bytes, 12);
        return (a, b, c, d);
    }

    public static Guid GuidFromUInts(uint a, uint b, uint c, uint d)
    {
        byte[] guidData = new byte[16];
        Array.Copy(BitConverter.GetBytes(a), guidData, 4);
        Array.Copy(BitConverter.GetBytes(b), 0, guidData, 4, 4);
        Array.Copy(BitConverter.GetBytes(c), 0, guidData, 8, 4);
        Array.Copy(BitConverter.GetBytes(d), 0, guidData, 12, 4);
        return new Guid(guidData);
    }

    public static (uint, uint, uint, uint) ToUInts(this Guid guid)
    {
        var bytes = guid.ToByteArray();
        var a = BitConverter.ToUInt32(bytes, 0);
        var b = BitConverter.ToUInt32(bytes, 4);
        var c = BitConverter.ToUInt32(bytes, 8);
        var d = BitConverter.ToUInt32(bytes, 12);
        return (a, b, c, d);
    }
}
Run Code Online (Sandbox Code Playgroud)

还发现了受此启发的另一个解决方案:Converting System.Decimal to System.Guid

[StructLayout(LayoutKind.Explicit)]
struct GuidConverter
{
    [FieldOffset(0)]
    public decimal Decimal;
    [FieldOffset(0)]
    public Guid Guid;
    [FieldOffset(0)]
    public long Long1;
    [FieldOffset(8)]
    public long Long2;
}

private static GuidConverter _converter;
public static (long, long) FastGuidToLongs(this Guid guid)
{
    _converter.Guid = guid;
    return (_converter.Long1, _converter.Long2);
}
public static Guid FastLongsToGuid(long a, long b)
{
    _converter.Long1 = a;
    _converter.Long2 = b;
    return _converter.Guid;
}
Run Code Online (Sandbox Code Playgroud)