当变量超出范围时,我该怎么办?

时间:2019-02-20 20:07:19

标签: c#

编辑:因此,看起来唯一的方法就是使用IDisposable。我对此表示怀疑,但仍然有点不知所措。我可以为此编写一个类,该类接受@mjwills建议的Action,但是我个人仍然希望有一种方法可以不使用using块。诸如“ using(var foo = new Bar([action]);”)这样的替代语法非常有用。

在C#中,当变量超出范围时是否可以执行操作?在C ++中,当对象超出范围时,我将使用其析构函数执行某些操作,但是垃圾收集器意味着我无法(干净地)在C#中获得相同的行为。这就是我要用C ++编写的内容:

class SetOnDestruction
{
    bool& m_thingToSet;
    bool m_newValueForThing;

public:
    SetOnDestruction(bool& thingToSet, bool newValueForThing)
        : m_thingToSet(thingToSet)
        , m_newValueForThing(newValueForThing)
    {

    }

    ~SetOnDestruction()
    {
        m_thingToSet = m_newValueForThing;
    }
};

void ExampleUsage()
{
    bool thingToSet = true;
    {
        SetOnDestruction setter(thingToSet, false);
        // do some stuff here
    }
    // thingToSet should now be false
}

我不想使用IDisposable,因为那样的话我会将函数包装在大的using块中,实际上只是一些语法糖。

有人知道相关的东西吗?

1 个答案:

答案 0 :(得分:-1)

如果您要销毁非托管资源,实际上我们可以使用析构函数,例如

~SetOnDestruction()
{
  /* destruction things */
}

但是,当垃圾回收器销毁对象因而不确定时,就会调用此方法。

的另一种方式是使用IDisposable 有关IDisposable from MSDN here

的更多信息

编辑:为了纪念投反对票(和纯粹的利益),让我们看看是否应该这样做而不是是否可以这样做

假设可以通过调用类似这样的方法来强制执行本地范围

    class Program
    {
        static void Main(string[] args)
        {
            LocalScopeWrapper();
        }

        private static void LocalScopeWrapper() // maybe I could have a better name?
        {
            var testObj = new TestObj();
            testObj.Print();
            Console.WriteLine($"Total memory used before forced collect {GC.GetTotalMemory(false)}");
            testObj = null;
            GC.Collect(0); // Generation 0, lets only clear the smallest Small Object Heap
            Console.WriteLine($"Total memory used after forced collect {GC.GetTotalMemory(true)}");
        }

        private class TestObj
        {
            public void Print()
            {
                Console.WriteLine("HelloWorld");
            }
        }
    }

在这里,我们在将对象设置为null后强制收集对象。是有道理的,但并非完全符合我们的要求,正如《大鲸》所要求的不干净。

但是,我想看看我们是否模仿C ++行为,并且有可能。

我们可以使用Pinvoke和句柄将我们的对象传递给C / C ++库,并按此great answer by @xanatos

中所示进行免费调用

我很好奇我们在C#中会变得多么糟糕,这似乎是让Pinvoke删除我们鼻子下的东西来解决GC的终极方法。没什么用,但仍然很有趣。