C# - Criando e usando GUIDs (.NET Core)


 Hoje vamos recordar e acrescentar mais informação sobre como criar e usar GUIDs na linguagem C#.

Eu já publiquei alguns artigos sobre o Identificador Global Único, o famoso GUID, e retorno ao tema para acrescentar mais informações e recordar como criar e usar os GUIDs com o C#.

Um GUID é um número inteiro de 128 bits (16 bytes) que você pode usar em todos os computadores e redes sempre que um identificador exclusivo for necessário.

Quando dizemos que um GUID é exclusivo, o que realmente queremos dizer é que o espaço da chave é tão grande que é praticamente impossível para gerar acidentalmente o mesmo GUID duas vezes (assumindo que estamos gerando GUIDs aleatoriamente).

Então quantos GUIDs podemos gerar no Windows de forma exclusiva ?

A conta é simples, como os GUIDs possuem 128 bits , podemos gerar até 2^128 GUIDs ou algo em torno de 5.316.911.983.139.663.491.615.228.241.121.400.000 combinações possíveis.

E para gerar GUIDs no .NET Core usamos a struct GUID disponível no namespace System no assembly System.Runtime.dll.

Nota: Podemos também gerar GUIDs no SQL Server usando a função NEWID()

Como os GUIDs são representados ?

A seguir temos um exemplo de GUID :


    50b97e45-526c-4a8d-bddf-2d82e2f1b669
 

Vemos que um GUID usa a representação hexadecimal onde é organizado como uma sequência definida de 32 dígitos hexadecimais agrupados em blocos de 8-4-4-4-12.

Como criar um GUID ?

Para criar um GUID basta comandar :  Guid.NewGuid() e obter o retorno em um tipo GUID ou exibir o resultado.

        static void Main(string[] args)
        {
            Guid g = Guid.NewGuid();
            Console.WriteLine(g.ToString());
            Console.ReadLine();
        }

No exemplo estamos convertendo o GUID gerado para uma string usando o método ToString().

Como criar um GUID vazio ?

Como um GUID é uma struct e não uma classe, ele é um tipo de valor e portanto não pode ter um valor null.

        static void Main(string[] args)
        {
            Guid id = new Guid();
            Console.WriteLine(id.ToString());

            if (id == Guid.Empty)
                Console.WriteLine("O Guid esta vazio");
            Console.ReadLine();
        }

Como podemos observar um Guid.Empty tem um valor de 00000000-0000-0000-0000-000000000000.

Você pode tirar proveito de um GUID vazio para compará-lo com outro objeto GUID e determinar se ele é diferente de zero.

O seguinte trecho de código ilustra isso.

    if (guid != Guid.Empty)
    {  
       //O objeto GUID contém valores não zeros
    }
    else
    {
        //O objeto GUID esta vazio
    } 

Nota: Você pode usar o Online GUID Generator para gerar até 2000 GUIDs de forma automática na web.

Agora esteja atento ao fato de que como um GUID é do tipo struct e não é um object , ou seja é um tipo de valor, se você passar um GUID para um método o seu valor não vai mudar.

Se você já possui um GUID armazenado como uma string, é possível analisá-lo usando os métodos:

  1. Guid.Parse - Funciona apenas se a string de entrada tiver um valor válido;
  2. Guid.TryParse - Tenta analisar um valor e o atribui a uma variável
    static void Main(string[] args)
    {
            var guid1 = Guid.Parse("fc072692-d322-448b-9b1b-ba3443943579");
            Console.WriteLine("Guid1: " + guid1);
            Guid.TryParse("fc072692-d322-448b-9b1b-ba3443943579", out var guid2);
            Console.WriteLine("Guid2: " + guid2);
            Console.ReadLine();
    }

Agora que você sabe que um Guid é composto de 16 bytes, você pode estar pensando:

 "Os hífens fazem parte desses bytes ? ".

A resposta é, não.

Os hífens fazem parte da representação de string padrão de um Guid.

Além disso, quando usamos o método ToString(), podemos especificar o formato de exibição desejado para os GUIDs.

Veja alguns formatos possíveis:

D: 32 dígitos, mas com os hífens. Esse é o padrão;
N: 32 dígitos, sem outros símbolos;
B: Usa os hífens e a string é envolta entre chaves
P: semelhante a B, mas com parênteses em vez de chaves
X:  Usa a representação hexadecimal do guid.

static void Main(string[] args)
{
   var meuGuid = Guid.NewGuid();
   Console.WriteLine("D \t" + meuGuid.ToString("D"));
   Console.WriteLine("N \t" + meuGuid.ToString("N"));
   Console.WriteLine("B \t" + meuGuid.ToString("B"));
   Console.WriteLine("P \t" + meuGuid.ToString("P"));
   Console.WriteLine("X \t" + meuGuid.ToString("X"));
   Console.ReadLine();
}

Resultado:



Se um GUID usa 16 bytes poderíamos supor que o comando sizeof (Guid) irá retornar o valor 16.

Certo ?

Não.

Na verdade o código nem compila, veja ...

Porque ?

Como o 'Guid 'não possui um tamanho predefinido, você pode usar sizeof somente em um contexto não seguro ou unsafe.

Isso ocorre porque o tamanho de um Guid é constante, mas a memória alocada pelo CLR não é necessáriamente constante (porque, para alguma arquitetura, ele pode adicionar um preenchimento no final, no início ou na memória alocada).

Assim, você pode obter o valor usando o operador unsafe :


Uma outra forma de obter o valor é usar o método Marshal.SizeOf do namespace System.Runtime.InteropeServices para um GUID gerado:

E estamos conversados.

"Porque, como o relâmpago ilumina desde uma extremidade inferior do céu até à outra extremidade, assim será também o Filho do homem no seu dia."
Lucas 17:24

Referências:


José Carlos Macoratti