【发布时间】:2013-09-09 20:08:55
【问题描述】:
我希望在 .resx 文件中使用某种唯一标识符,但它不允许密钥以数字开头。与其循环遍历 GUID,直到我得到一个以字母开头的 GUID,我想知道是否有另一种不包含数字或满足此要求的 UID 类型。
有什么想法吗?
【问题讨论】:
标签: c# guid uniqueidentifier uid
我希望在 .resx 文件中使用某种唯一标识符,但它不允许密钥以数字开头。与其循环遍历 GUID,直到我得到一个以字母开头的 GUID,我想知道是否有另一种不包含数字或满足此要求的 UID 类型。
有什么想法吗?
【问题讨论】:
标签: c# guid uniqueidentifier uid
如果您只想创建一个以字母开始的 Guid,您可以执行以下操作:
var b = Guid.NewGuid().ToByteArray();
b[3] |= 0xF0;
return new Guid(b);
这将始终生成一个以十六进制数字 F 开头的 GUID。
要创建一个不包含任何数字的 Guid,您可以使用如下内容:
return new Guid(Guid.NewGuid().ToByteArray()
.Select(b => (byte)(((b % 16) < 10 ? 0xA : b) |
(((b >> 4) < 10 ? 0xA : (b >> 4)) << 4)))
.ToArray());
这将测试每个十六进制数字(每个字节两个),如果小于 A,则将其强制转换为 A。
上述两种解决方案都会生成真正的Guid 对象,尽管添加的限制确实在一定程度上降低了生成的 GUID 的唯一性(在第二个示例中更是如此)。如果您不关心输出是实际的 GUID,您可以简单地将十六进制数字重新映射到其他内容并将结果返回一个字符串,正如其他人所建议的那样。 FWIW,这是我能想到的最短解决方案:
return String.Concat(Guid.NewGuid().ToString("N").Select(c => (char)(c + 17)));
这会将十六进制数字 0 到 9 映射到字符 A 到 J,并将十六进制数字 A - F 映射到字符 r 到 w。它还生成一个没有任何连字符的字符串。例如:
Before: e58d0f329a2f4615b922ecf53dcd090a
After: vFIuAwDCJrCwEGBFsJCCvtwFDutuAJAr
当然,如果您不喜欢这里的混合大小写,您可以将其全部转换为大写或小写。
【讨论】:
Guid.NewGuid 的新 GUID,完全没有修改,也不能保证是唯一的。这只是一个非常、非常、非常高的概率。
如何生成一个唯一编号,然后在其前面加上一个字母?所以不是
1234
你会使用
a1234
只要您为标识符选择的算法保证一个唯一的数字,这应该可以正常工作。如果需要,它还可以让您去除前缀并再次将标识符用作数字。
【讨论】:
您可以编写和使用伪随机序列生成器。这是给出基本思想的一个:
class RandomLetterSequence {
private static Random r;
private static char MinChar = (char) 0x0061;
private static char MaxChar = (char) 0x007A;
public static string RandomSequence() {
return RandomSequence(32);
}
public static string RandomSequence(int length) {
if (r == null)
r = new Random();
var sb = new StringBuilder();
for (int i = length; i >= 0; i--) {
sb.Append((char)(r.Next(MinChar, MaxChar)));
}
return sb.ToString();
}
}
使用此实现,可以生成 26^32 种符合您要求的不同序列:
【讨论】:
假设您不需要它成为有效的 Guid(您指的是“某种唯一标识符”),只需创建一个基于字符串的 guid(使用 Guid.NewGuid().ToString())然后将第一个数字映射到合适的字母,例如0=G、1=H、2=I 等
【讨论】:
只需编写您自己的类似 GUID 的生成器,有效的字符将是 a-z(您也可以使用 A-Z 来增加概率的数量)。
【讨论】:
生成新的 GUID 并将字符 0-9 替换为字符 g-p。
【讨论】:
@p.s.w.g 提供了很好的解决方案。
您可以将他/她的建议写为扩展:
using System;
using System.Linq;
namespace YourApp.Extensions.GuidExtensions
{
public static class Extension
{
public static Guid FirstLetter(this Guid obj)
{
var b = obj.ToByteArray();
b[3] |= 0xF0;
return new Guid(b);
}
public static Guid OnlyLetters(this Guid obj)
{
var ba = obj.ToByteArray();
return new Guid(
ba.Select(b => (byte)(((b % 16) < 10 ? 0xA : b) |
(((b >> 4) < 10 ? 0xA : (b >> 4)) << 4)))
.ToArray()
);
}
}
}
然后在应用的某处使用它:
// ...
using YourApp.Extensions.GuidExtensions;
// ...
class SomeClass {
Guid SomeMethodWithFirstLetter() {
return Guid.NewGuid().FirstLetter();
}
Guid SomeMethodWithOnlyLetters() {
return Guid.NewGuid().OnlyLetters();
}
}
【讨论】: