Je veux essayer de convertir une chaîne en Guid, mais je ne veux pas me fier à la capture d'exceptions (
- pour des raisons de performances - les exceptions coûtent cher
- pour des raisons de convivialité - le débogueur apparaît
- pour des raisons de conception - l'attendu n'est pas exceptionnel
En d'autres termes, le code:
public static Boolean TryStrToGuid(String s, out Guid value)
{
try
{
value = new Guid(s);
return true;
}
catch (FormatException)
{
value = Guid.Empty;
return false;
}
}
ne convient pas.
J'essaierais d'utiliser RegEx, mais comme le guid peut être entre parenthèses, entre accolades, aucun enveloppé, cela rend les choses difficiles.
De plus, je pensais que certaines valeurs Guid ne sont pas valides (?)
Mise à jour 1
ChristianK avait une bonne idée d'attraper seulement FormatException
, plutôt que tout. L'échantillon de code de la question a été modifié pour inclure une suggestion.
Mise à jour 2
Pourquoi s'inquiéter des exceptions levées? Est-ce que je m'attends vraiment à des GUID invalides si souvent?
La réponse est oui . Voilà pourquoi je me sers TryStrToGuid - Je me attends de mauvaises données.
Exemple 1 Les extensions d'espace de noms peuvent être spécifiées en ajoutant un GUID à un nom de dossier . Je suis peut-être en train d'analyser les noms de dossiers, de vérifier si le texte après la finale . est un GUID.
c:\Program Files
c:\Program Files.old
c:\Users
c:\Users.old
c:\UserManager.{CE7F5AA5-6832-43FE-BAE1-80D14CD8F666}
c:\Windows
c:\Windows.old
Exemple 2 J'exécute peut-être un serveur Web très utilisé qui souhaite vérifier la validité de certaines données postées. Je ne veux pas que des données non valides bloquent des ressources de 2 à 3 ordres de grandeur plus élevées que nécessaire.
Exemple 3 Je suis peut-être en train d'analyser une expression de recherche saisie par un utilisateur.
S'ils entrent des GUID, je veux les traiter spécialement (comme rechercher spécifiquement cet objet, ou mettre en évidence et mettre en forme ce terme de recherche spécifique dans le texte de la réponse.)
Mise à jour 3 - Benchmarks de performance
Testez la conversion de 10 000 bons guides et 10 000 mauvais guides.
Catch FormatException:
10,000 good: 63,668 ticks
10,000 bad: 6,435,609 ticks
Regex Pre-Screen with try-catch:
10,000 good: 637,633 ticks
10,000 bad: 717,894 ticks
COM Interop CLSIDFromString
10,000 good: 126,120 ticks
10,000 bad: 23,134 ticks
ps je ne devrais pas avoir à justifier une question.
4.0
. C'est pourquoi la question et la réponse acceptée sont telles qu'elles sont.Réponses:
Benchmarks de performance
Réponse COM Intertop (la plus rapide):
Bottom line: Si vous devez vérifier si une chaîne est un GUID et que vous vous souciez des performances, utilisez COM Interop.
Si vous devez convertir un GUID dans une représentation String en Guid, utilisez
la source
Une fois que .net 4.0 est disponible, vous pouvez utiliser
Guid.TryParse()
.la source
Vous n'allez pas aimer ça, mais qu'est-ce qui vous fait penser que la capture de l'exception sera plus lente?
Combien de tentatives échouées pour analyser un GUID attendez-vous par rapport aux tentatives réussies?
Mon conseil est d'utiliser la fonction que vous venez de créer et de profiler votre code. Si vous trouvez que cette fonction est vraiment un point chaud puis le corriger , mais pas avant.
la source
Dans .NET 4.0, vous pouvez écrire comme suit:
la source
Je voudrais au moins le réécrire comme:
Vous ne voulez pas dire "GUID invalide" sur SEHException, ThreadAbortException ou tout autre élément fatal ou non lié.
Mise à jour : à partir de .NET 4.0, un nouvel ensemble de méthodes est disponible pour Guid:
Guid.TryParse
Guid.TryParseExact
Vraiment, ceux-ci devraient être utilisés (ne serait-ce que pour le fait qu'ils ne sont pas implémentés "naïvement" en utilisant try-catch en interne).
la source
L'interopérabilité est plus lente que de simplement attraper l'exception:
Dans la bonne voie, avec 10000 Guids:
Sur le chemin malheureux:
C'est plus cohérent, mais c'est aussi toujours plus lent. Il me semble que vous feriez mieux de configurer votre débogueur pour qu'il ne casse que sur les exceptions non gérées.
la source
Eh bien, voici la regex dont vous aurez besoin ...
Mais ce n'est que pour les débutants. Vous devrez également vérifier que les différentes parties telles que la date / heure sont dans des plages acceptables. Je ne peux pas imaginer que cela soit plus rapide que la méthode try / catch que vous avez déjà décrite. J'espère que vous ne recevez pas autant de GUID invalides pour justifier ce type de vérification!
la source
Si vous optez pour l'approche try / catch, vous pouvez ajouter l'attribut [System.Diagnostics.DebuggerHidden] pour vous assurer que le débogueur ne s'arrête pas même si vous l'avez défini pour casser lors du lancer.
la source
S'il est vrai que l'utilisation d'erreurs est plus coûteuse, la plupart des gens croient que la majorité de leurs GUID seront générés par ordinateur, donc un
TRY-CATCH
n'est pas trop cher car il ne génère que des coûts sur leCATCH
. Vous pouvez vous le prouver par un simple test des deux (utilisateur public, pas de mot de passe).Voici:
la source
J'ai eu une situation similaire et j'ai remarqué que la chaîne invalide n'avait presque jamais 36 caractères. Donc, sur la base de ce fait, j'ai un peu changé votre code pour obtenir de meilleures performances tout en restant simple.
la source
Autant que je sache, il n'y a pas quelque chose comme Guid.TryParse dans mscrolib. Selon la source de référence, le type Guid a un constructeur méga-complexe qui vérifie toutes sortes de formats de guid et essaie de les analyser. Il n'y a pas de méthode d'assistance que vous pouvez appeler, même par réflexion. Je pense que vous devez rechercher des parseurs Guid tiers ou écrire le vôtre.
la source
Exécutez le GUID potentiel via un RegEx ou un code personnalisé qui effectue une vérification de cohérence pour vous assurer que le strig ressemble au moins à un GUID et se compose uniquement de caractères valides (et peut-être qu'il semble correspondre au format global). S'il ne réussit pas le contrôle de cohérence, renvoyez une erreur - cela éliminera probablement la grande majorité des chaînes invalides.
Ensuite, convertissez la chaîne comme vous l'avez fait ci-dessus, en récupérant toujours l'exception pour les quelques chaînes non valides qui passent par la vérification de cohérence.
Jon Skeet a fait une analyse pour quelque chose de similaire pour analyser Ints (avant TryParse était dans le Framework): vérifier si une chaîne peut être convertie en Int32
Cependant, comme AnthonyWJones l'a indiqué, vous ne devriez probablement pas vous inquiéter à ce sujet.
la source
la source
Le ctor de Guid est à peu près une regex compilée, de cette façon vous obtiendrez exactement le même comportement sans surcharge de l'exception.
Une solution encore plus cool serait d'instrumenter dynamiquement une méthode, en remplaçant «lancer nouveau» à la volée.
la source
Je vote pour le lien GuidTryParse posté ci-dessus par Jon ou une solution similaire (IsProbablyGuid). Je vais en écrire un comme ceux de ma bibliothèque de conversion.
Je pense qu'il est totalement nul que cette question soit si compliquée. Le mot clé "is" ou "as" conviendrait parfaitement SI un Guid pouvait être nul. Mais pour une raison quelconque, même si SQL Server est d'accord avec cela, .NET ne l'est pas. Pourquoi? Quelle est la valeur de Guid.Empty? C'est juste un problème stupide créé par la conception de .NET, et cela me dérange vraiment lorsque les conventions d'un langage se renversent. La réponse la plus performante à ce jour a été d'utiliser COM Interop parce que le Framework ne le gère pas correctement? "Cette chaîne peut-elle être un GUID?" devrait être une question à laquelle il est facile de répondre.
Se fier à l'exception levée est OK, jusqu'à ce que l'application soit sur Internet. À ce stade, je viens de me préparer à une attaque par déni de service. Même si je ne suis pas «attaqué», je sais que certains yahoo vont faire un singe avec l'URL, ou peut-être que mon service marketing enverra un lien malformé, et alors mon application devra subir un impact assez lourd en termes de performances qui POURRAIT apporter sur le serveur parce que je n'ai pas écrit mon code pour gérer un problème qui NE DEVRAIT PAS arriver, mais nous savons tous QU'IL ARRIVERA.
Cela brouille un peu la ligne sur "Exception" - mais en fin de compte, même si le problème est rare, si cela peut arriver suffisamment de fois dans un court laps de temps pour que votre application se bloque en réparant les captures de tout cela, alors je pense que lancer une exception est mauvaise forme.
TheRage3K
la source
si TypeOf ctype (myvar, Object) Is Guid alors .....
la source
la source
Avec une méthode d'extension en C #
la source