Saltar al contenido

Artículos, tutoriales, trucos, curiosidades, reflexiones y links sobre programación web ASP.NET Core, MVC, Blazor, SignalR, Entity Framework, C#, Azure, Javascript... y lo que venga ;)

17 años online

el blog de José M. Aguilar

Inicio El autor Contactar

Artículos, tutoriales, trucos, curiosidades, reflexiones y links sobre programación web
ASP.NET Core, MVC, Blazor, SignalR, Entity Framework, C#, Azure, Javascript...

¡Microsoft MVP!
martes, 31 de enero de 2023
.NET

Seguimos hablando de problemas que es habitual solucionarlos de una determinada manera, quizás por costumbre, quizás por pereza, o tal vez por desconocimiento de que haya otras formas de hacerlo. En este caso, hablaremos de una necesidad que probablemente habréis tenido alguna vez: transformar un GUID a una cadena de caracteres eliminando los habituales guiones.

Es decir, dado un GUID con el valor 1f5772a6-91ca-4035-8b6d-9676ec6d0eaa, queremos obtener su representación como cadena de caracteres, pero eliminando los guiones, resultando "1f5772a691ca40358b6d9676ec6d0eaa".

Una de las fórmulas que más veces he visto, y que de hecho he utilizado muchísimas veces en el pasado, es el popular método Replace(): transformamos a cadena el GUID original, y luego usamos este método para sustituir los guiones por una cadena vacía. Simple y eficaz.

var guid = Guid.NewGuid();
Console.WriteLine(guid); // 88cf50c1-aa37-46e0-a487-a90e2fba534e

var str = guid.ToString().Replace("-", string.Empty);
Console.WriteLine(str); // 88cf50c1aa3746e0a487a90e2fba534e

Sin embargo, no es la mejor, ni la más eficiente, ni la más cómoda forma de conseguirlo. El método ToString() de la estructura Guid soporta varios tipos de formato específicamente destinados a obtener distintas representaciones del GUID como cadena de texto.

Formato Retorna
N 32 dígitos, sin guiones.
D 32 dígitos separados por guiones.
B 32 dígitos separados por guiones, con llaves al principio y final.
P dígitos separados por guiones, con paréntesis al principio y final.
X Cuatro valores hexadecimales entre llaves. El último grupo son ocho valores hexadecimales también encerrados entre llaves.

Lo veremos mejor con un ejemplo:

var guid = Guid.NewGuid();
Console.WriteLine("N: " + guid.ToString("N")); 
// 7884fab97a844340ab7139a9f8ef0f20
Console.WriteLine("D: " + guid.ToString("D")); 
// 7884fab9-7a84-4340-ab71-39a9f8ef0f20
Console.WriteLine("B: " + guid.ToString("B")); 
// {7884fab9-7a84-4340-ab71-39a9f8ef0f20}
Console.WriteLine("P: " + guid.ToString("P")); 
// (7884fab9-7a84-4340-ab71-39a9f8ef0f20)
Console.WriteLine("X: " + guid.ToString("X")); 
// {0x7884fab9,0x7a84,0x4340,{0xab,0x71,0x39,0xa9,0xf8,0xef,0x0f,0x20}}

Por tanto, con guid.ToString("N") podemos conseguir el resultado que andábamos buscando sin necesidad de hacer el Replace(). Sin duda es un código más conciso (aunque ciertamente sería discutible si más legible, porque la intencionalidad de Replace("-", string.Empty) es bastante clara).

Otro tema a tener en cuenta también es el rendimiento y consumo de recursos. Podemos comprobar cómo se comportan estas dos opciones en términos de rendimiento y memoria creando una aplicación de consola con benchmarks usando el implacable BenchmarkDotNet:

using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Running;

BenchmarkRunner.Run<GuidReplace>(); // Go!

[MemoryDiagnoser]
public class GuidReplace
{
    [Benchmark]
    public string UsingReplace()
    {
        return Guid.NewGuid().ToString().Replace("-", string.Empty);
    }

    [Benchmark]
    public string UsingToString()
    {
        return Guid.NewGuid().ToString("N");
    }
}

El resultado que obtenemos es el siguiente:

|        Method |     Mean |   Error |  StdDev |  Gen 0 | Allocated |
|-------------- |---------:|--------:|--------:|-------:|----------:|
|  UsingReplace | 249.2 ns | 2.32 ns | 2.17 ns | 0.0219 |     184 B |
| UsingToString | 164.7 ns | 0.43 ns | 0.40 ns | 0.0105 |      88 B |

Como podemos observar, usar ToString("N") tarda como un 30% menos que sustituir los guiones a mano, y además alojando la mitad de elementos en el heap. Tiene bastante sentido, pues la primera opción tiene que almacenar primero la cadena resultante de llamar a ToString(), y luego la resultante de hacer el reemplazo.

Publicado en Variable not found.

2 Comentarios:

ripprip dijo...

Llevo años en la industria y porque hasta ahora encuentro esto? ahh? debi parecer un idiota jajaja interesante la web como tal, hay demasiada informacion util y relevante , gracias

José María Aguilar dijo...

Hola! Me alegra saber que los contenidos te parecen útiles :)

Muchas gracias por comentar!