title: Building a thread-safe GUID increment'er
body: <p>In my below code, I'm locking the guid, to try and make it thread safe.
  With my example application, I will get a "duplicate key" about every 10 times I run the program.  Aka, I get a duplicate, which is not what I need.</p>
  
  <p>Is there anyway to make the ".NextGuid" thread safe?</p>
  
  <pre><code>using System;    
  namespace MyConsoleOne.BAL
  {
      public class GuidStore
      {
          private static object objectlock = new object();    
          private Guid StartingGuid { get; set; }    
          private Guid? LastGuidHolder { get; set; }    
          public GuidStore(Guid startingGuid)
          {
              this.StartingGuid = startingGuid;
          }
  
          public Guid? GetNextGuid()
          {
              lock (objectlock)
              {
                  if (this.LastGuidHolder.HasValue)
                  {
                      this.LastGuidHolder = Increment(this.LastGuidHolder.Value);
                  }
                  else
                  {
                      this.LastGuidHolder = Increment(this.StartingGuid);
                  }
              }    
              return this.LastGuidHolder;
          }
  
          private Guid Increment(Guid guid)
          {    
              byte[] bytes = guid.ToByteArray();    
              byte[] order = { 15, 14, 13, 12, 11, 10, 9, 8, 6, 7, 4, 5, 0, 1, 2, 3 };    
              for (int i = 0; i &lt; 16; i++)
              {
                  if (bytes[order[i]] == byte.MaxValue)
                  {
                      bytes[order[i]] = 0;
                  }
                  else
                  {
                      bytes[order[i]]++;
                      return new Guid(bytes);
                  }
              }    
              throw new OverflowException("Guid.Increment failed.");
          }
      }
  }
  
  using MyConsoleOne.BAL;
  using System;
  using System.Collections.Generic;
  using System.Linq;
  using System.Text;
  using System.Threading.Tasks;
  
  namespace MyConsoleOne
  {
      class Program
      {
          static void Main(string[] args)
          {
              GuidStore gs = new GuidStore(Guid.NewGuid());
  
              for (int i = 0; i &lt; 1000; i++)
              {
                  Console.WriteLine(i);
                  Dictionary&lt;Guid, int&gt; guids = new Dictionary&lt;Guid, int&gt;();
                  Parallel.For(0, 1000, j =&gt;
                  {
                      Guid? currentGuid = gs.GetNextGuid();
                      guids.Add(currentGuid.Value, j);
                      Console.WriteLine(currentGuid);
                  }); // Parallel.For
              }    
              Console.WriteLine("Press ENTER to Exit");
              Console.ReadLine();
          }
      }
  }
  </code></pre>
  
  <p>My code is a combination of:</p>
  
  <ul>
  <li><a href="https://stackoverflow.com/questions/14647811/making-guid-properties-threadsafe">Making Guid properties threadsafe</a></li>
  <li><a href="https://stackoverflow.com/questions/30404965/increment-guid-in-c-sharp">Increment Guid in C#</a></li>
  </ul>
  
  <p>Since I'm getting "Why not use Guid.NewGuid" questions, I'll provide the reason here:</p>
  
  <p>I have a parent process that has a uniqueidentifier which is created by Guid.NewGuid().  I'll refer to this as the "parent guid".  That parent process will create N number of files.  If I were writing from scratch, I would just append the "N" at the end of the filename.  So if the parent Guid was "11111111-1111-1111-1111-111111111111" for example, I would write files </p>
  
  <pre><code>"11111111-1111-1111-1111-111111111111_1.txt"
  "11111111-1111-1111-1111-111111111111_2.txt"
  "11111111-1111-1111-1111-111111111111_3.txt"
  </code></pre>
  
  <p>, etc, etc.  However, via the existing "contract" with the client ::: the filename must have a (unique) Guid in it and not have that "N" (1,2,etc,etc) value in the filename (this "contract" has been in existence for years, so its set in stone pretty much).  With the functionality laid out here, I'll be able to keep the "contract", but have file names that are loosely tied to the "parent" Guid (which again the parent is generated by Guid.NewGuid()).  Collision is <strong>NOT</strong> an issue with the filenames (they are put under a distinct folder for the 'process' execution).  Collision is an issue with the "parent" Guid.  But again, that is already handled with Guid.NewGuid.</p>
  
  <p>So with a starting Guid of "11111111-1111-1111-1111-111111111111", I'll be able to write filenames like:</p>
  
  <pre><code>OTHERSTUFF_111111111-1111-1111-1111-111111111112_MORESTUFF.txt
  OTHERSTUFF_111111111-1111-1111-1111-111111111113_MORESTUFF.txt
  OTHERSTUFF_111111111-1111-1111-1111-111111111114_MORESTUFF.txt
  OTHERSTUFF_111111111-1111-1111-1111-111111111115_MORESTUFF.txt
  OTHERSTUFF_111111111-1111-1111-1111-111111111116_MORESTUFF.txt
  OTHERSTUFF_111111111-1111-1111-1111-111111111117_MORESTUFF.txt
  OTHERSTUFF_111111111-1111-1111-1111-111111111118_MORESTUFF.txt
  OTHERSTUFF_111111111-1111-1111-1111-111111111119_MORESTUFF.txt
  OTHERSTUFF_111111111-1111-1111-1111-11111111111a_MORESTUFF.txt
  OTHERSTUFF_111111111-1111-1111-1111-11111111111b_MORESTUFF.txt
  </code></pre>
  
  <p>So in my example above, the "parent guid" is represented by "this.StartingGuid"....and then I get "incremented" guid's off of that.</p>
  
  <p>And also.  I can write better unit-tests, because now I will know the filenames ahead of time.</p>
  
  <p>APPEND:</p>
  
  <p>Final Code Version:</p>
  
  <pre><code>public class GuidStore
  {
      private static object objectlock = new object();
  
      private static int[] byteOrder = { 15, 14, 13, 12, 11, 10, 9, 8, 6, 7, 4, 5, 0, 1, 2, 3 };
  
      private Guid StartingGuid { get; set; }
  
      private Guid? LastGuidHolder { get; set; }
  
      public GuidStore(Guid startingGuid)
      {
          this.StartingGuid = startingGuid;
      }
  
      public Guid GetNextGuid()
      {
          return this.GetNextGuid(0);
      }
  
      public Guid GetNextGuid(int firstGuidOffSet)
      {
          lock (objectlock)
          {
              if (this.LastGuidHolder.HasValue)
              {
                  this.LastGuidHolder = Increment(this.LastGuidHolder.Value);
              }
              else
              {
                  this.LastGuidHolder = Increment(this.StartingGuid);
                  for (int i = 0; i &lt; firstGuidOffSet; i++)
                  {
                      this.LastGuidHolder = Increment(this.LastGuidHolder.Value);
                  }
              }
  
              return this.LastGuidHolder.Value;
          }
      }
  
      private static Guid Increment(Guid guid)
      {
          var bytes = guid.ToByteArray();
          var canIncrement = byteOrder.Any(i =&gt; ++bytes[i] != 0);
          return new Guid(canIncrement ? bytes : new byte[16]);
      }
  }
  </code></pre>
  
  <p>and UnitTests:</p>
  
  <pre><code>public class GuidStoreUnitTests
  {
      [TestMethod]
      public void GetNextGuidSimpleTest()
      {
          Guid startingGuid = new Guid("11111111-1111-1111-1111-111111111111");
          GuidStore gs = new GuidStore(startingGuid);
  
  
          List&lt;Guid&gt; guids = new List&lt;Guid&gt;();
  
          const int GuidCount = 10;
  
          for (int i = 0; i &lt; GuidCount; i++)
          {
              guids.Add(gs.GetNextGuid());
          }
  
          Assert.IsNotNull(guids);
          Assert.AreEqual(GuidCount, guids.Count);
          Assert.IsNotNull(guids.FirstOrDefault(g =&gt; g == new Guid("11111111-1111-1111-1111-111111111112")));
          Assert.IsNotNull(guids.FirstOrDefault(g =&gt; g == new Guid("11111111-1111-1111-1111-111111111113")));
          Assert.IsNotNull(guids.FirstOrDefault(g =&gt; g == new Guid("11111111-1111-1111-1111-111111111114")));
          Assert.IsNotNull(guids.FirstOrDefault(g =&gt; g == new Guid("11111111-1111-1111-1111-111111111115")));
          Assert.IsNotNull(guids.FirstOrDefault(g =&gt; g == new Guid("11111111-1111-1111-1111-111111111116")));
          Assert.IsNotNull(guids.FirstOrDefault(g =&gt; g == new Guid("11111111-1111-1111-1111-111111111117")));
          Assert.IsNotNull(guids.FirstOrDefault(g =&gt; g == new Guid("11111111-1111-1111-1111-111111111118")));
          Assert.IsNotNull(guids.FirstOrDefault(g =&gt; g == new Guid("11111111-1111-1111-1111-111111111119")));
          Assert.IsNotNull(guids.FirstOrDefault(g =&gt; g == new Guid("11111111-1111-1111-1111-11111111111a")));
          Assert.IsNotNull(guids.FirstOrDefault(g =&gt; g == new Guid("11111111-1111-1111-1111-11111111111b")));
      }
  
      [TestMethod]
      public void GetNextGuidWithOffsetSimpleTest()
      {
          Guid startingGuid = new Guid("11111111-1111-1111-1111-111111111111");
          GuidStore gs = new GuidStore(startingGuid);
  
          List&lt;Guid&gt; guids = new List&lt;Guid&gt;();
  
          const int OffSet = 10;
  
          guids.Add(gs.GetNextGuid(OffSet));
  
          Assert.IsNotNull(guids);
          Assert.AreEqual(1, guids.Count);
  
          Assert.IsNotNull(guids.FirstOrDefault(g =&gt; g == new Guid("11111111-1111-1111-1111-11111111111c")));
      }
  
      [TestMethod]
      public void GetNextGuidMaxRolloverTest()
      {
          Guid startingGuid = new Guid("ffffffff-ffff-ffff-ffff-ffffffffffff");
          GuidStore gs = new GuidStore(startingGuid);
  
          List&lt;Guid&gt; guids = new List&lt;Guid&gt;();
  
          const int OffSet = 10;
  
          guids.Add(gs.GetNextGuid(OffSet));
  
          Assert.IsNotNull(guids);
          Assert.AreEqual(1, guids.Count);
  
          Assert.IsNotNull(guids.FirstOrDefault(g =&gt; g == Guid.Empty));
      }
  
      [TestMethod]
      public void GetNextGuidThreadSafeTest()
      {
          Guid startingGuid = Guid.NewGuid();
          GuidStore gs = new GuidStore(startingGuid);
  
          /* The "key" of the ConcurrentDictionary must be unique, so this will catch any duplicates */
          ConcurrentDictionary&lt;Guid, int&gt; guids = new ConcurrentDictionary&lt;Guid, int&gt;();
          Parallel.For(
              0,
              1000,
              j =&gt;
              {
                  Guid currentGuid = gs.GetNextGuid();
                  if (!guids.TryAdd(currentGuid, j))
                  {
                      throw new ArgumentOutOfRangeException("GuidStore.GetNextGuid ThreadSafe Test Failed");
                  }
              }); // Parallel.For
      }
  
      [TestMethod]
      public void GetNextGuidTwoRunsProduceSameResultsTest()
      {
          Guid startingGuid = Guid.NewGuid();
  
          GuidStore gsOne = new GuidStore(startingGuid);
  
          /* The "key" of the ConcurrentDictionary must be unique, so this will catch any duplicates */
          ConcurrentDictionary&lt;Guid, int&gt; setOneGuids = new ConcurrentDictionary&lt;Guid, int&gt;();
          Parallel.For(
              0,
              1000,
              j =&gt;
              {
                  Guid currentGuid = gsOne.GetNextGuid();
                  if (!setOneGuids.TryAdd(currentGuid, j))
                  {
                      throw new ArgumentOutOfRangeException("GuidStore.GetNextGuid ThreadSafe Test Failed");
                  }
              }); // Parallel.For
  
          gsOne = null;
  
          GuidStore gsTwo = new GuidStore(startingGuid);
  
          /* The "key" of the ConcurrentDictionary must be unique, so this will catch any duplicates */
          ConcurrentDictionary&lt;Guid, int&gt; setTwoGuids = new ConcurrentDictionary&lt;Guid, int&gt;();
          Parallel.For(
                  0,
                  1000,
                  j =&gt;
                  {
                      Guid currentGuid = gsTwo.GetNextGuid();
                      if (!setTwoGuids.TryAdd(currentGuid, j))
                      {
                          throw new ArgumentOutOfRangeException("GuidStore.GetNextGuid ThreadSafe Test Failed");
                      }
                  }); // Parallel.For
  
          bool equal = setOneGuids.Select(g =&gt; g.Key).OrderBy(i =&gt; i).SequenceEqual(
                           setTwoGuids.Select(g =&gt; g.Key).OrderBy(i =&gt; i), new GuidComparer&lt;Guid&gt;());
  
          Assert.IsTrue(equal);
      }
  }
  
  internal class GuidComparer&lt;Guid&gt; : IEqualityComparer&lt;Guid&gt;
  {
      public bool Equals(Guid x, Guid y)
      {
          return x.Equals(y);
      }
  
      public int GetHashCode(Guid obj)
      {
          return 0;
      }
  }
  </code></pre>