web-dev-qa-db-fra.com

Comparaison de Guid avec une chaîne

Je suis surpris de ne pas avoir pu trouver de réponse à cela ni dans Google ni ici sur SO, mais quelle est la meilleure façon de comparer un string à Guid en tenant compte de la casse, et , le cas échéant, performances

const string sid = "XXXXX-...."; // This comes from a third party library
Guid gid = Guid.NewGuid(); // This comes from the db

if (gid.ToString().ToLower() == sid.ToLower())

if (gid == new Guid(sid))

// Something else?

pdate: Pour rendre cette question plus convaincante, j'ai changé sid en const... et puisque vous ne pouvez pas avoir un Guid const c'est le vrai problème que je traite.

13
Serj Sagan

Ne comparez pas Guids en tant que chaînes, et ne créez pas de nouveau Guid à partir d'une chaîne juste pour le comparer à un Guid existant.

Mis à part les performances, il n’existe pas un seul format standard pour représenter un Guid sous forme de chaîne, vous courez donc le risque de comparer des formats incompatibles et vous devez ignorer la casse, soit en configurant String.Compare pour ce faire ou en convertissant chacun en minuscules.

Une manière beaucoup plus idiomatique et performante consiste à créer un Guid statique et en lecture seule à partir de la valeur de chaîne constante et à toutes les comparaisons utilisant l'égalité Guid native:

const string sid = "3f72497b-188f-4d3a-92a1-c7432cfae62a";
static readonly Guid guid = new Guid(sid);

void Main()
{
    Guid gid = Guid.NewGuid(); // As an example, say this comes from the db

    Measure(() => (gid.ToString().ToLower() == sid.ToLower()));
    // result: 563 ms

    Measure(() => (gid == new Guid(sid)));
    // result: 629 ms

    Measure(() => (gid == guid));
    // result: 10 ms

}

// Define other methods and classes here
public void Measure<T>(Func<T> func)
{
    Stopwatch sw = new Stopwatch();

    sw.Start();
    for(int i = 1;i<1000000;i++)
    {
        T result = func();
    }
    sw.Stop();

    Console.WriteLine(sw.ElapsedMilliseconds);
}

Ainsi, la comparaison de chaînes et la création d'un nouveau Guid à partir de la valeur constante sont 50 à 60 fois plus chères que la comparaison du Guid à un Guid statique et en lecture seule créé à partir de la constante valeur.

14
D Stanley

Élaboration sur D Stanley

const string sid = "3f72497b-188f-4d3a-92a1-c7432cfae62a";
static readonly Guid guid = new Guid(sid);

static void Main()
{
    Guid gid = Guid.NewGuid(); // As an example, say this comes from the db

    Measure(() => (gid.ToString().ToLower() == sid.ToLower()));
    // result: 177 ms
    Measure(() => (gid == new Guid(sid)));
    // result: 113 ms
    Measure(() => (gid == guid));
    // result: 6 ms
    Measure(() => (gid == Guid.Parse(sid)));
    // result: 114 ms
    Measure(() => (gid.Equals(sid)));
    // result: 7 ms

}

// Define other methods and classes here
public static void Measure<T>(Func<T> func)
{
    System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch();

    sw.Start();
    for (int i = 1; i < 1000000; i++)
    {
        T result = func();
    }
    sw.Stop();

    Console.WriteLine(sw.ElapsedMilliseconds);
}

Donc, si vous ne pouvez pas stocker votre guid dans une constante, le Guid.Equals () intégré est votre option préférée.

0
Kevin V