簡體   English   中英

增加C#中的Guid

[英]Increment Guid in C#

我有一個具有guid變量的應用程序,該變量需要是唯一的(當然)。 我知道統計上任何guid應該被認為是唯一的,但由於開發/測試環境的原因,可以多次看到相同的值。 所以當發生這種情況時,我想“增加”Guid的值,而不是僅僅創建一個全新的值。 似乎沒有一種簡單的方法可以做到這一點。 我找到了一個黑客,我將作為一個可能的答案發布,但想要一個更清潔的解決方案。

你可以得到guid的字節組件,所以你可以解決這個問題:

static class GuidExtensions
{
    private static readonly int[] _guidByteOrder =
        new[] { 15, 14, 13, 12, 11, 10, 9, 8, 6, 7, 4, 5, 0, 1, 2, 3 };
    public static Guid Increment(this Guid guid)
    {
        var bytes = guid.ToByteArray();
        bool carry = true;
        for (int i = 0; i < _guidByteOrder.Length && carry; i++)
        {
            int index = _guidByteOrder[i];
            byte oldValue = bytes[index]++;
            carry = oldValue > bytes[index];
        }
        return new Guid(bytes);
    }
}

編輯:現在正確的字節順序

感謝Thomas Levesque的字節順序,這里有一個漂亮的LINQ實現:

static int[] byteOrder = { 15, 14, 13, 12, 11, 10, 9, 8, 6, 7, 4, 5, 0, 1, 2, 3 };

static Guid NextGuid(Guid guid)
{
    var bytes = guid.ToByteArray();
    var canIncrement = byteOrder.Any(i => ++bytes[i] != 0);
    return new Guid(canIncrement ? bytes : new byte[16]);
}

請注意,如果你設法將它增加到那么遠,它將包裝到Guid.Empty

如果你繼續增加單個bytes副本而不是依次調用每個GUID上的ToByteArray會更有效。

已驗證的有序字符串解決方案:

    private static Guid Increment(Guid guid)
    {

        byte[] bytes = guid.ToByteArray();

        byte[] order = { 15, 14, 13, 12, 11, 10, 9, 8, 6, 7, 4, 5, 0, 1, 2, 3 };

        for (int i = 0; i < 16; i++)
        {
            if (bytes[order[i]] == byte.MaxValue)
            {
                bytes[order[i]] = 0;
            }
            else
            {
                bytes[order[i]]++;
                return new Guid(bytes);
            }
        }

        throw new OverflowException("Congratulations you are one in a billion billion billion billion etc...");

    }

驗證:

    private static Guid IncrementProof(Guid guid, int start, int end)
    {

        byte[] bytes = guid.ToByteArray();

        byte[] order = { 15, 14, 13, 12, 11, 10, 9, 8, 6, 7, 4, 5, 0, 1, 2, 3 };

        for (int i = start; i < end; i++)
        {
            if (bytes[order[i]] == byte.MaxValue)
            {
                bytes[order[i]] = 0;
            }
            else
            {
                bytes[order[i]]++;
                return new Guid(bytes);
            }
        }

        throw new OverflowException("Congratulations you are one in a billion billion billion billion etc...");

    }

    static void Main(string[] args)
    {

        Guid temp = new Guid();

        for (int j = 0; j < 16; j++)
        {
            for (int i = 0; i < 255; i++)
            {
                Console.WriteLine(temp.ToString());
                temp = IncrementProof(temp, j, j + 1);
            }
        }

    }

可能的解決方案 - 我認為這可行(未經過實際測試),但需要更好的解決方案。

public static Guid Increment(this Guid value)
{
    var bytes = value.ToByteArray();
    // Note that the order of bytes in the returned byte array is different from the string representation of a Guid value.
    //  Guid:       00112233-4455-6677-8899-aabbccddeeff
    //  byte array: 33 22 11 00 55 44 77 66 88 99 AA BB CC DD EE FF
    // So the byte order of the following indexes indicates the true low-to-high sequence
    if (++bytes[15] == 0) if (++bytes[14] == 0) if (++bytes[13] == 0) if (++bytes[12] == 0) if (++bytes[11] == 0) if (++bytes[10] == 0) // normal order
     if (++bytes[9] == 0) if (++bytes[8] == 0) // normal order
      if (++bytes[6] == 0) if (++bytes[7] == 0) // reverse order
       if (++bytes[5] == 0) if (++bytes[4] == 0) // reverse order
        if (++bytes[3] == 0) if (++bytes[2] == 0) if (++bytes[1] == 0) { ++bytes[0]; } // reverse order
    return new Guid(bytes);
}

編輯:這是我最終使用的代碼; 對於一般技術的上述答案的道具,雖然沒有“未經檢查”的條款,但在某些情況下它們都會拋出異常。 但我也嘗試使下面的內容盡可能可讀。

private static int[] _guidByteOrder = { 15, 14, 13, 12, 11, 10, 9, 8, 6, 7, 4, 5, 0, 1, 2, 3 };
public static Guid NextGuid(this Guid guid)
{
    var bytes = guid.ToByteArray();
    for (int i = 0; i < 16; i++)
    {
        var iByte = _guidByteOrder[i];
        unchecked { bytes[iByte] += 1; }
        if (bytes[iByte] != 0)
            return new Guid(bytes);
    }
    return Guid.Empty;
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM