Darkleo’s Blog
Ein Schatz, der seinen Besitzer überallhin begleitet.

Eigener Datentyp SmallGuid

January 24th, 2008 by darkleo

Eine Anforderung wieso dieser Datentype entstand ist, für URLs müssten Zeichen gesparrt werden und trotzdem wollten wir nicht auf die Eindeutigkeit von Guid verzichten.

Anforderungen:

  1. URL Übertragbar, darf keine Sonderzeichen enthalten
  2. Soll die gleiche Zufallsrate besitzen wie Guid und soll in Guid Convertierbar sein

Ich habe Intern einen Guid Typen verwendet und durch Codierung von Base64 aus  dem Raum 15 in Raum 64 übertragen, dabei werden weniger Zeichen für die gleiche Information benötigt, Rund 30% weniger von 32 auf 22 Zeichen.

Mit Zip Algorithen würden ich Punkt 1 nicht erfühlen und String Comprimierung funktioniert erst ab 60-90 Zeichen.
Durch Imlicit opertaor kann ich diesen Datentypen in Guid und String implizit umwandeln.
Implizit heisst ohne es direkt anzugeben: z.B. bei Verbinden von Strings "SmallGuid: "+new SmallGuid().

public static implicit operator Guid(SmallGuid item)
{
 return item.Guid;
}

public static implicit operator string(SmallGuid item)
{
 return item.SmallString;
}

explizit operator: http://msdn2.microsoft.com/en-us/library/xhbhezf4.aspx
implizit operator: http://msdn2.microsoft.com/en-us/library/z5z9kes2.aspx

Kern Methoden der Codierung:

public static string GuidToString(Guid guid)
{
string ret = string.Empty;
byte[] b = guid.ToByteArray();
ret =
Convert.ToBase64String(b).Remove(22);
return ret;
}
public static Guid StringToGuid(string smallString)
{
Guid ret = new Guid();
byte[] b = Convert.FromBase64String(smallString + "==");
ret =
new Guid(b);
return ret;
}

Test:
Guid g = new Guid("11111111111111111111111111111111");
Console.WriteLine("Guid: " + g);
Console.WriteLine("Guid.Length: " + g.ToString().Length);
SmallGuid sg = new SmallGuid(g);
Console.WriteLine("SmallGuid: " + sg.SmallString); // auch ("SmallGuid: "+sg) funktioniert
Console.WriteLine("SmallGuid.Length: " + sg.SmallString.Length);
Console.WriteLine("Cast to Guid: "+(Guid)sg);
Console.WriteLine("Guid(N).Length: " + ((Guid)sg).ToString("N").Length);
Console.ReadKey();

Ausgabe:
Guid: 11111111-1111-1111-1111-111111111111
Guid.Length: 36
SmallGuid: EREREREREREREREREREREQ
SmallGuid.Length: 22
Cast to Guid: 11111111-1111-1111-1111-111111111111
Guid(N).Length: 32

Download

Posted in .NET, C#, Klasse

One Response

  1. Thomas

    Hi,

    nett - aber so richtig viele Zeichen spart man damit ja noch nicht, und ganz URL-tauglich ist es auch nicht, weil mit relativ hoher Wahrscheinlichkeit auch / generiert werden.

    Ja das Stimmt 3f sollte im Guid nicht Vorkommen, erweiterungswürdig und damit würde man paar Prozent genauigkeit verlieren
    Wenn man in einer Url nur 120 zur Verfügung hat, standen für Key und Text 100 zur Verfügung und 10 Zeichen mehr oder weniger machen schon einen Unterschied.
    Theoretisch wäre es möglich in der DB Key-Guid zu speichern, aber ein kleinerer GuidTyp fand ich mal eine Gute Idee und vor Allem sollte es nur zeigen, wie implizit und explizit funktioniert.

    Lösung

    RFC 3548 beschreibt ebenfalls diese Kodierung, schlägt allerdings eine leicht modifizierte Variante vor, welche benutzt werden soll, falls die Zeichen + und / nicht angewendet werden können. (Zum Beispiel bei Dateinamen oder anderen Umgebungen, wo diese Zeichen eine Sonderbedeutung haben.) Diese Zeichen werden durch - (Minus, ASCII 2Dhex) und _ (Unterstrich, ASCII 5Fhex) ersetzt.

Leave a Comment

Please note: Comment moderation is enabled and may delay your comment. There is no need to resubmit your comment.