Creating a Safer Guid

Guids (Globally Unique Identifers) are great. They are very useful when uniqueness is important, maybe for identification later on. They are fairly efficient to create and are even human readable. So yeah, Guids are pretty great… except when they aren’t.

A common use case for a Guid (for me at least) is to receive it as a set of characters and then convert it to an actual Guid (in C#). This usually looks like this:

public void CallWithGuidAsString(string guid) 
{
    Guid newGuid = new Guid(guid);

    // Do stuff with guid.
}

The issue with this is that it is not exception safe. You see the Guid  constructor will throw an exception if the provided string is not a valid Guid. That means the correct code actually looks like this:

public void CallWithGuidAsString(string guid)
{
    Guid newGuid = Guid.Empty;

    try
    {
        newGuid = new Guid(guid);
    }
    catch (Exception ex)
    {
        Console.WritleLine("Invalid Guid")
    }

    // Do stuff with Guid.
}

This is the correct exception safe way of dealing with a Guid that, quite frankly, is out of your hands (of course, you could have finer grain control over the exception thrown but that’s not really the point here). It’s a little verbose but not the end of the world, unless you find yourself dealing with it constantly. I propose a better solution: a safe exception safe way of creating Guids without the need for these try/catch blocks. I also implemented this solution:

public void CallWithGuidAsString(string guid)
{
    Guid newGuid = new SafeGuid(guid);

    // Do stuff with Guid.
}

SafeGuid is a simple wrapper which will always return a Guid and in exceptional situations simply return an empty Guid. It is available on GitHub as a VisualStudio solution for a library with unit tests included. For those of you who’d rather see the class here it is, it’s quite simple:

public class SafeGuid
{
    private readonly Guid _guid;

    public SafeGuid()
    {
        _guid = Guid.NewGuid();
    }

    public SafeGuid(string guid)
    {
        try
        {
            _guid = new Guid(guid);
        }
        catch
        {
            _guid = Guid.Empty;
        }
    }

    public SafeGuid(Guid guid)
    {
        _guid = guid;
    }

    public override string ToString()
    {
        return _guid.ToString();
    }

    public override bool Equals(object obj)
    {
        var guid = obj as SafeGuid;
        return guid == null ? false : this.Equals(guid);
    }

    public override int GetHashCode()
    {
        return _guid.GetHashCode();
    }

    private bool Equals(SafeGuid guid)
    {
        return _guid.Equals(guid._guid);
    }

    public static implicit operator Guid(SafeGuid guid)
    {
        return guid._guid;
    }

    public static implicit operator SafeGuid(Guid guid)
    {
        return new SafeGuid(guid);
    }

    public static Guid Parse(string guid)
    {
        return new SafeGuid(guid);
    }
}

It looks much better on GitHub with fancy fixin’s like comments and such!

Leave a Reply

Your email address will not be published. Required fields are marked *

*