假设我有 
void foo () {
    Bar bar = new Bar(); // bar is never referred to after this line
    // (1)
    doSomethingWithoutBar();
}
在(1),是对象 bar 指着 合格 垃圾收集?或者 bar 还必须超出范围?它是否有所作为 GC.Collect 被称为 doSomethingWithoutBar?
这与知道Bar是否有(C#)析构函数或者像这样的类似的东西有关。
             
            
            
            
一旦确定不再使用对象,对象就有资格进行垃圾收集。这完全有可能 bar 将在变量超出范围之前进行垃圾收集。
证明:
using System;
class Bar
{
    ~Bar() { Console.WriteLine("Finalized!"); }
}
class Program
{
    static void Main(string[] args)
    {
        Bar bar = new Bar();
        GC.Collect();
        GC.WaitForPendingFinalizers();
        Console.WriteLine("Press any key to exit...");
        Console.ReadLine();
    }
}
跑进 发布模式 (因为它没有在调试模式下收集)。
输出:
敲定!
按任何一个键退出...
它也适用 ideone 它使用Mono。输出是一样的。
 
                
从快速阅读规范看,它看起来像是特定的实现。它的 允许 垃圾收集它,但不是 需要 至。
我从第10.9节“自动内存管理”中的说明中得到了这个 ECMA规范:
[注意:实现可能会选择分析代码来确定
  对象的引用可以在将来使用。对于
  例如,如果范围内的局部变量是唯一存在的
  引用一个对象,但永远不会引用该局部变量
  在当前执行的任何可能的继续执行中
  在程序中指出, 实施可能(但不是必需的)
  to)将对象视为不再使用。结束说明]
强调我的。
 
                
如果没有定义您所指的CLR的版本,那就是 不可能很难确定你在这里看到的行为。
一个 假想 在此示例中,CLR可以假设以下情况属实:
- 的构造函数 Bar什么也没做
- 没有初始化的字段(即对象构造没有潜在的副作用)
完全无视这条线 Bar bar = new Bar(); 因为它“无所事事”而优化它。
就我的记忆而言,在当前版本的CLR中 bar 在构建之后,有资格进行垃圾收集。
 
                
马克回答了这个问题,但这是解决方案:
void foo () {
    Bar bar = new Bar(); // bar is never referred to after this line
    // (1)
    doSomethingWithoutBar();
    GC.KeepAlive(bar); // At the point where you no longer need it
}
 
                
这肯定会发生。例如,这是一个演示,当您仍在执行其构造函数时,可以最终确定实例:
class Program
{
    private static int _lifeState;
    private static bool _end;
    private sealed class Schrodinger
    {
        private int _x;
        public Schrodinger()
        {
            //Here I'm using 'this'
            _x = 1;
            //But now I no longer reference 'this'
            _lifeState = 1;
            //Keep busy to provide an opportunity for GC to collect me
            for (int i=0;i<10000; i++)
            {
                var garbage = new char[20000];
            }
            //Did I die before I finished being constructed?
            if (Interlocked.CompareExchange(ref _lifeState, 0, 1) == 2)
            {
                Console.WriteLine("Am I dead or alive?");
                _end = true;
            }
        }
        ~Schrodinger()
        {
            _lifeState = 2;
        }
    }
    static void Main(string[] args)
    {
        //Keep the GC churning away at finalization to demonstrate the case
        Task.Factory.StartNew(() =>
            {
                while (!_end)
                {
                    GC.Collect();
                    GC.WaitForPendingFinalizers();
                }
            });
        //Keep constructing cats until we find the desired case
        int catCount = 0;
        while (!_end)
        {
            catCount++;
            var cat = new Schrodinger();
            while (_lifeState != 2)
            {
                Thread.Yield();
            }
        }
        Console.WriteLine("{0} cats died in the making of this boundary case", catCount);
        Console.ReadKey();
    }
}
为了使其工作,您需要发出Release版本并在Visual Studio外部运行它(否则调试器会插入阻止该效果的代码。)我已经使用VS 2010目标.NET 4.0 x64对此进行了测试。
您可以在“保持忙碌”循环中调整迭代,以影响Cat完成构建之前完成的清理概率。