Test if string is a guid without throwing exceptions?

c#, guid, parsing, string

Solution

Performance Benchmarks

Catch exception:
   10,000 good:    63,668 ticks
   10,000 bad:  6,435,609 ticks

Regex Pre-Screen:
   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

COM Intertop (Fastest) Answer:

/// <summary>
/// Attempts to convert a string to a guid.
/// </summary>
/// <param name="s">The string to try to convert</param>
/// <param name="value">Upon return will contain the Guid</param>
/// <returns>Returns true if successful, otherwise false</returns>
public static Boolean TryStrToGuid(String s, out Guid value)
{
   //ClsidFromString returns the empty guid for null strings   
   if ((s == null) || (s == ""))   
   {      
      value = Guid.Empty;      
      return false;   
   }

   int hresult = PInvoke.ObjBase.CLSIDFromString(s, out value);
   if (hresult >= 0)
   {
      return true;
   }
   else
   {
      value = Guid.Empty;
      return false;
   }
}


namespace PInvoke
{
    class ObjBase
    {
        /// <summary>
        /// This function converts a string generated by the StringFromCLSID function back into the original class identifier.
        /// </summary>
        /// <param name="sz">String that represents the class identifier</param>
        /// <param name="clsid">On return will contain the class identifier</param>
        /// <returns>
        /// Positive or zero if class identifier was obtained successfully
        /// Negative if the call failed
        /// </returns>
        [DllImport("ole32.dll", CharSet = CharSet.Unicode, ExactSpelling = true, PreserveSig = true)]
        public static extern int CLSIDFromString(string sz, out Guid clsid);
    }
}

Bottom line: If you need to check if a string is a guid, and you care about performance, use COM Interop.

If you need to convert a guid in String representation to a Guid, use

new Guid(someString);

Problem

I want to try to convert a string to a Guid, but I don't want to rely on catching exceptions ( - for performance reasons - exceptions are expensive - for usability reasons - the debugger pops up - for design reasons - the expected is not exceptional In other words the code: ``` public static Boolean TryStrToGuid(String s, out Guid value) { try { value = new Guid(s); return true; } catch (FormatException) { value = Guid.Empty; return false; } } ``` is not suitable. I would try using RegEx, but since the guid can be parenthesis wrapped, brace wrapped, none wrapped, makes it hard. Additionally, I thought certain Guid values are invalid(?) Update 1 ChristianK had a good idea to catch only `FormatException`, rather than all. Changed the question's code sample to include suggestion. Update 2 Why worry about thrown exceptions? Am I really expecting invalid GUIDs all that often? The answer is yes. That is why I am using TryStrToGuid - I am expecting bad data. Example 1 Namespace extensions can be specified by appending a GUID to a folder name. I might be parsing folder names, checking to see if the text after the final . is a 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 ``` Example 2 I might be running a heavily used web-server wants to check the validity of some posted back data. I don't want invalid data tying up resources 2-3 orders of magnitude higher than it needs to be. Example 3 I might be parsing a search expression entered by a user. If they enter GUID's I want to process them specially (such as specifically searching for that object, or highlight and format that specific search term in the response text.) Update 3 - Performance benchmarks Test converting 10,000 good Guids, and 10,000 bad Guids. ``` 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 ``` p.s. I shouldn't have to justify a question.

Original source