title: Is safe to not call GC.KeepAlive() in this scenario?
body: <p>let's say we have the following code running in release build:</p>
  <pre><code>class SomeClass
  {
    // This field is initialized somewhere in the constructor (not shown here).
    public SomeOtherClass Value;
  
    ...
  }
  
  class SomeOtherClass {
    ...
    public void Call() {
       ...
    }
  }
  ...
  
  static void Main()
  {
    SomeClass obj = new SomeClass();
    SomeOtherMethod(obj.Value);
    ...
  }
  
  static void SomeOtherMethod(SomeOtherClass value) {
    ... // do sth else first
    value.Call();   // value is a reference that points to `obj.Value` object in heap
  }
  </code></pre>
  <p>I saw code like this all the time and at that time I was not familiar with how GC works.
  But now I know that the garbage collect may collect obj just after the runtime has retrieved obj.Value i.e. before SomeOtherMethod() is even called. So there is a chance (although unlikely, but still possible) that when <code>SomeOtherMethod</code> execute and before manipulate <code>obj.Value</code> the argument, <code>obj</code> has been marked as unreachable (therefore its member <code>Value</code> is also marked as unreachable) and collected by GC and their memory is recliamed, so it is illegal for <code>SomeOtherMethod</code> to access <code>Value</code>.</p>
  <p>So I think a solution is to add <code>GC.KeepAlive(obj)</code> or <code>GC.KeepAlive(obj.Value)</code> as:</p>
  <pre><code>void MyMethod()
  {
    SomeClass obj = new SomeClass();
    SomeOtherMethod(obj.Value);
    ...
    GC.KeepAlive(obj);   //  or GC.KeepAlive(obj.Value);
  }
  </code></pre>
  <p>But I don't see many people(senior developer) doing this, and the code always running correctly without throwing any exception. So is my understanding incorrect or CLR has a workaround on this?</p>