5

我们有一个遗留要求,将现在新迁移int的 ID 值存储到一个guid类型中,以用于与 ID 无关的数据类型(基本上是利用“全局唯一”部分的旧代码,guid以便在一个列中包含所有可能的 ID /场地)。

guid由于这个要求,有一个后续要求以人类可读的方式嵌入实体的整数 ID 。这很重要,也是目前阻止我直接处理字节值的原因。

目前,我有以下内容:

    public static byte[] IntAsHexBytes(int value)
    {
        return BitConverter.GetBytes(Convert.ToInt64(value.ToString(), 16));
    }

    public static Guid EmbedInteger(int id)
    {
        var ib = IntAsHexBytes(id);

        return new Guid(new byte[]
            {
                0,0,0,0,0,0,1,64,ib[7],ib[6],ib[5],ib[4],ib[3],ib[2],ib[1],ib[0]
            });
    }

它将 的可视化表示int视为十六进制值 ( value.ToString()),将转换为long( Convert.ToInt64(value.ToString(), 16)) 并将字节从 抓取long到扁平化以在特定结构byte[]中创建 a 。guid

因此,给定int42,当您将 42 视为十六进制并将其转换为66 时long将得到 66 的字节,然后放入 66 的字节中guid

"00000000-0000-4001-0000-000000000042"

和一个int给出379932126

"00000000-0000-4001-0000-000379932126"

所以最终结果是将整数放入guid最后 12 位数字中,使其在视觉上看起来像整数 42(即使基础整数值是 66)。

这比使用连接构造字符串以输入构造函数快大约 30%-40% new Guid(string),但我觉得我错过了避免首先对字符串做任何事情的解决方案。

所涉及的实际时间非常小,因此作为性能改进,它可能无法证明努力是合理的。

纯粹是为了我自己的好奇心,看看是否有更快的方法来解决这个问题。我在这里发帖是因为我是一个长期的 SO 用户,但我很担心这是否是一个代码审查问题,尽管我没有直接要求任何反对我的代码的东西,它只是展示了我想要作为输出。

提供的整数范围是 0 到int.MaxValue

更新:为了完整起见,这是我们目前拥有的以及我正在测试的内容:

string s = string.Format("00000000-0000-4001-0000-{0:D12}", id);
return new Guid(s);

我上面的其他代码比这快了大约 30%。

4

2 回答 2

1

认为这会做你想要的。不确定它是否比您的代码更有效,但至少要短一些。:)

public static Guid EmbedInteger(int id)
{
    string guid = string.Format("00000000-0000-4001-0000-{0,12:D12}", id);
    return new Guid(guid);
}

它通过使用数字格式 12:D12 来工作,这会导致输入数字被格式化为字段宽度为 12 且带有前导零的小数。

于 2012-07-31T11:13:09.480 回答
1

好的,这是另一个完全避免字符串的版本。希望这可能会更好。:)

public static Guid EmbedInteger(int id)
{
    byte[] bytes = new byte[8];
    int i = 0;

    while (id > 0)
    {
        int remainder = id%100;
        bytes[i++] = (byte)(16*(remainder/10) + remainder%10);
        id /= 100;
    }

    return new Guid(0, 0, 0x4001, bytes[7], bytes[6], bytes[5], bytes[4], bytes[3], bytes[2], bytes[1], bytes[0]);
}

Adam Houldsworth:更新:此代码也可以展开:

int remainder = id % 100;
bytes[0] = (byte)(16 * (remainder / 10) + remainder % 10);
id /= 100;
if (id == 0) return;
remainder = id % 100;
bytes[1] = (byte)(16 * (remainder / 10) + remainder % 10);
id /= 100;
if (id == 0) return;
remainder = id % 100;
bytes[2] = (byte)(16 * (remainder / 10) + remainder % 10);
id /= 100;
if (id == 0) return;
remainder = id % 100;
bytes[3] = (byte)(16 * (remainder / 10) + remainder % 10);
id /= 100;
if (id == 0) return;
remainder = id % 100;
bytes[4] = (byte)(16 * (remainder / 10) + remainder % 10);
于 2012-07-31T11:29:34.557 回答