12

So in C# the switch statement only supports integral types (not Guids), so a simple O(1) comparison table doesn't look possible.

What is the most computationally efficient way to match on a Guid

At first I thought

if(gMyGuid == new Guid("VALUE"))
else if (gMyGuid == new Guid("VALUE2")
else if (gMyGuid == new Guid("VALUE3")
...
else if (gMyGuid == new Guid("VALUEn")

However by doing this I'm creating a new instance of the Guid each time for a comparison. I could convert the Guid to a string then compare on the string but the string comparison is a pretty long string for comparison.

Any advise is gratefully received.

John Mitchell
  • 9,653
  • 9
  • 57
  • 91
  • 3
    compare the string representation instead? – chiccodoro Jun 22 '12 at 12:22
  • 2
    The C# `switch` statement does not only support integral types. For example, it also supports strings. However, it requires that the case labels to test for be known at compile time. – O. R. Mapper Jun 22 '12 at 12:23
  • 1
    or you define the GUID's that you want to compare to only once and reuse them every time you do the comparison. That way you could rely on the people that implemented the GUID's comparison to optimize that. – chiccodoro Jun 22 '12 at 12:23
  • Thats what I originally thought but the length of the guid is still pretty long for a string comparison. – John Mitchell Jun 22 '12 at 12:23
  • 2
    BTW: How important is performance in this piece of code? You know - if your app includes file system access, web traffic or database access, "microoptimizing" this piece of code might be overkill... The question would then rather be "how can I make it most readable and maintainable" – chiccodoro Jun 22 '12 at 12:29
  • @chiccodoro you are entirely correct, right now its more for a thought process and understanding than it is about using it in a real world environment. I was just doing something similar and wondered what the best case I could get out if it was. – John Mitchell Jun 22 '12 at 12:31
  • 1
    o.k. O. R. Mapper's solution would make the code more readable and maintainable *and* also probably is pretty performant since it only instanciates the GUIDs once and then uses the GUID's comparision implementation which seems to be the quickest according to the links referenced by Gene S :-) – chiccodoro Jun 22 '12 at 12:34
  • Today with C# 7 you can sort of do this. Refer this answer: https://stackoverflow.com/a/53829606/661933 – nawfal May 10 '19 at 10:51

6 Answers6

18

You can create a System.Collections.Generic.Dictionary<Guid, ...> where ... is something useful to you.

Upon program startup, fill the dictionary with the guids and values that you need to recognize.

Then, use the TryGetValue method of the dictionary to retrieve a value by its guid.

I haven't stated anything literal for ... because I don't know what you want to do with the guids. Maybe you want to run some function, then a method pointer (Func<T> or something like that) might be appropriate, or otherwise an interface type that provides the method you want to invoke. This depends on the context/purpose of that guid comparing code.

O. R. Mapper
  • 20,083
  • 9
  • 69
  • 114
  • 4
    If you don't really have a value that you need to match to, you can just use a `HashMap` instead of a `Dictionary`. I suspect that you do, however, because you're using it in an if/else chain. – Tim S. Jun 22 '12 at 12:53
  • A dictionary of functions is akin to strategy pattern and using this approach will cause issues of it's own: http://stackoverflow.com/questions/2316189/guid-newguid-gethashcode-for-db – oasten Jun 22 '12 at 20:30
7

with c#7 you can now use switch with Pattern Matching for this purpose.

switch (gMyGuid )
{
    case var g when (g == new Guid("VALUE")):
        break;
    case var g when (g == new Guid("VALUE2")):
        break;
    case var g when (g == new Guid("VALUEN")):
        break;
    default:
        break;
}

This also works if you have defined static readonly new Guid"..") variables.

Manfred Wippel
  • 1,946
  • 1
  • 15
  • 14
3

Create the compare values as static so you only created them once.

At the top of your class add:

private static Guid guidVal1 = new Guid("VALUE");

And then in your method:

if(gMyGuid == guidVal1)
else if .... 
Richard Hooper
  • 809
  • 1
  • 12
  • 27
  • Sorry this is probably my bad sample, I've updated the problem, there isn't only 1 comparitor guid, theres quite a few, so I'd need to create a new guid for each comparitor thats the issue I'm trying to avoid. – John Mitchell Jun 22 '12 at 12:26
2

If you're really concerned about performance, the constructors using numeric arguments are faster than the Guid(string) constructor. No strings involved and no need to parse anything.

This is the implementation of one of them:

public Guid(int a, short b, short c, byte d, byte e, byte f, byte g, byte h, byte i, byte j, byte k)
{
    this._a = a;
    this._b = b;
    this._c = c;
    this._d = d;
    this._e = e;
    this._f = f;
    this._g = g;
    this._h = h;
    this._i = i;
    this._j = j;
    this._k = k;
}

Sure, it's not as pretty to look at, but i think it's the fastest constructor possible. Also, you could of course store all your comparison Guids in a Dictionary and use the values in it to store a handler for each.

Botz3000
  • 39,020
  • 8
  • 103
  • 127
1

I'd create a HashSet(T) of Guids, initialize it at startup.

Instead of the lengty 'if , if, if ' you get a

if (GuidHashSet.Contains(gMyGuid)) {}

and you could add new Guids to the HashSet if required. HashSet Contains() is an O(1) operation.

Make them all Guids (just once) as Guid == Guid uses the internal data of the Guid to compare them (equals is overloaded in Guid.cs). So comparing Guid == Guid is fastest. Which the HastSet will do.

IvoTops
  • 3,463
  • 17
  • 18
0

The Guid equality operator (==) is overloaded so to compare just the values:

http://msdn.microsoft.com/en-us/library/system.guid.op_equality(v=VS.90).aspx

if(gMyGuid == myGuid)
...
Dave New
  • 38,496
  • 59
  • 215
  • 394