title: How does this snippet of GCNotification work? CLR via C#
body: <p>I'm reading CLR via C# now. In chapter 21 The Managed Heap and Garbage Collection, it shows a class that can raise an event when gc occurs. I only have some vague concept about the function of the class, but I can't understand how exactly the class work and how can I use it and how it interact with the GenObject class?
  I've finished the Event Chapter.</p>
  
  <pre><code>public static class GCNotification
      {
          private static Action&lt;Int32&gt; s_gcDone = null;
  
          public static event Action&lt;Int32&gt; GCDone
          {
              add
              {
                  if (s_gcDone == null)
                  {
                      new GenObject(0);
                      new GenObject(2);
                  }
                  s_gcDone += value;
              }
              remove { s_gcDone -= value; }
          }
  
          private sealed class GenObject
          {
              private readonly Int32 m_generation;
  
              public GenObject(Int32 generation)
              {
                  m_generation = generation;
              }
  
              //Finalize 方法
              ~GenObject()
              {
                  if (GC.GetGeneration(this) &gt;= m_generation)
                  {
                      Action&lt;Int32&gt; temp = Volatile.Read(ref s_gcDone);
                      if (temp != null)
                      {
                          temp(m_generation);
                      }
                  }
  
                  if ((s_gcDone != null) &amp;&amp;
                      !AppDomain.CurrentDomain.IsFinalizingForUnload() &amp;&amp;
                      !Environment.HasShutdownStarted)
                  {
  
                      if (m_generation == 0)
                      {
                          new GenObject(0);
                      }
                      else
                      {
                          GC.ReRegisterForFinalize(this);
                      }
                  }
                  else
                  {
                      //放过对象
                  }
              }
          }
      }
  </code></pre>