C# VB.Net的作用域及其缩小方法

C# VB.Net的作用域及其缩小方法,c#,vb.net,scope,reflector,C#,Vb.net,Scope,Reflector,如果我想缩小C#中变量的范围,我可以引入额外的大括号-即: class Program { static void Main(string[] args) { myClass x = new myClass(); x.MyProperty = 1000; Console.WriteLine("x = " + x.MyProperty); { myClass y = new myClass()

如果我想缩小C#中变量的范围,我可以引入额外的大括号-即:

class Program
{
    static void Main(string[] args)
    {
        myClass x = new myClass();
        x.MyProperty = 1000;
        Console.WriteLine("x = " + x.MyProperty);

        {
            myClass y = new myClass();
            y.MyProperty = 2000;
            Console.WriteLine("y = " + y.MyProperty);
        }

        myClass y2 = new myClass();
        y2.MyProperty = 3000;
        Console.WriteLine("y2 = " + y2.MyProperty);

    }

    class myClass
    {

        public int MyProperty { get; set; }

    }
}
在ide中,我不能再引用新大括号引入的范围之外的y。我本以为这意味着变量y可以用于垃圾收集

(值得注意的是,当使用reflector查看编译后的代码时,使用或不使用附加大括号似乎没有区别)

在使用VB.net时,有没有类似的方法来缩小范围?这对内部作用域中定义的变量何时可以被垃圾收集有任何影响吗?

在C中,至少在没有附加调试器的情况下,这对垃圾收集没有任何影响-GC能够计算出变量最后一次读取的时间,并且变量在该时间点之后不算为GC根。例如:

 object y = new object();
 Console.WriteLine("y is still a GC root");
 Console.WriteLine(y);
 Console.WriteLine("y is not a GC root now");
 y = null;
 Console.WriteLine("y is still not a GC root");
(就术语而言,变量本身不会被收集,只是当它作为垃圾收集器的“根”计数时,它会阻止它所引用的对象被收集。)

当您连接了一个调试器时,GC会更加保守,因为您可能希望在最后一个“正常”读取点之后检查变量的值

在我看来,减少作用域的主要好处是清晰。如果变量的作用域很窄,那么当你不看那一段代码时,你可以忘记它(假设它没有被委托等捕获)


我不知道VB是否有任何等价于语句块的东西,除了作用域之外没有其他原因;最接近的等价物可能是带有语句的
。。。或者一个
Do
循环而False语句,两者都不完全令人满意。

在vb中创建新作用域似乎不是一个好方法,但您可以创建一个只运行一次的循环,然后在该循环中声明变量

MSDN对变量的生存期有这样的说法:

即使变量的范围仅限于一个块,其生存期仍然是整个过程的生存期。如果在过程中多次输入块,每个块变量将保留其以前的值。为了避免在这种情况下出现意外结果,最好在块的开头初始化块变量

src:


似乎只有在过程完成后,变量才会进行垃圾收集,但即使如此,除非堆变得拥挤,否则垃圾收集器也不会运行。对于小型应用程序来说,最有可能的情况是,在关闭应用程序之前,没有任何东西会被垃圾收集。

有趣的是,developerFusion c#-vb.net代码转换器会转换

 {
    myClass y = new myClass();
    y.MyProperty = 2000;
    Console.WriteLine("y = " + y.MyProperty);
 }


作为限制范围的一种方式。我很惊讶它会让人费心记住

为什么不创建一些方法呢?应该在方法中定义范围。一旦你退出这个方法,你就离开了这个范围——干净而简单。您这样做的方式非常非正统-如果您担心范围爬行(您正在描述的内容),我建议您坚持惯例并使用方法。

关于范围,.Net帮助提到with块定义了范围的块级别,它适用于块内定义的任何内容,但不适用于块的主题。通过使用With 1 end With或With True end With可以缩小范围,但它仍然感觉很粗糙…在VB.NET中GC行为是相同的。VB.NET没有等效的语句块,只是用于作用域-请参阅MSDN条目(来自paintballbob的回答),您对作用域和生存期的看法是正确的。关于垃圾收集只在过程完成后发生的说法不太正确。这可能发生得更早,见Skeet的答案。
If True Then
   Dim y As New [myClass]()
   y.MyProperty = 2000
   Console.WriteLine("y = " & y.MyProperty)
End If