在 C# 早期使用浮动花括号释放变量

Sup*_*est 2 c# optimization garbage-collection coding-style curly-braces

C# 变量在类型声明的地方(例如string s;)被实例化,并在当前作用域的右大括号处被释放:

// Operates with Q memory
void FantasyMethod() {
    var o = new BigObject();

    {
        var temp = new BigObject();
        Populate(temp); // Populates o1 with N megabytes of data

        o = PerformSomeOperationsOn(temp); // Returns a BigObject of size M (M is close to N)

        // Currently, M+N memory is occupied, we have Q-M-N free
    }

    // Let's tell the garbage collector to catch up
    GC.Collect();
    GC.WaitForPendingFinalizers();

    // Currently, M memory is occupied

    DoUsefulStuffWith(o); // This method can only work if at least Q-M-N/2 memory is free
}
Run Code Online (Sandbox Code Playgroud)

这样做的一个好处是我可以在函数返回之前释放大变量。在上面的(琐碎的)块中,我通过在不再需要时立即处理一个大变量来利用我有限的可用内存。

  1. 以上正确吗?
  2. 这样做是否是个好主意(我对支持和反对的论点感兴趣,而不是个人意见或偏好)?提取裸大括号块作为一种方法是否会降低使用内存的效率?如果出于可读性原因我不想创建新方法怎么办?

Ed *_* S. 5

这样做的一个好处是我可以在函数返回之前释放大变量。

不。C# 不是 C++,对象没有析构函数,并且不能保证对象在离开其声明范围并且不存在对其的有效引用时会被回收。

如果您需要这种级别的可预测性,那么您不应该使用托管语言,句号。确实存在有助于缓解 C# 中内存压力的技术,但它们并不经常需要,而且您永远无法获得像 C 或 C++ 这样的语言所提供的控制级别。

根据您的编辑:

GC.Collect尝试运行 GC pass,它不保证它。 GC.WaitForPendingFinalizers阻塞,直到所有被标记为终结的对象都运行了它们的终结器。

如果对象实现了终结器并且没有通过调用 SuppressFinalize 禁用终结,则该对象将被放置在标记为准备终结的对象列表中。垃圾收集器为此列表中的对象调用 Finalize 方法并从列表中删除条目。此方法会阻塞,直到所有终结器都运行完成。