【问题标题】:Scope and how to narrow it using VB.Net范围以及如何使用 VB.Net 缩小范围
【发布时间】:2009-09-28 06:02:16
【问题描述】:

如果我想在 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 可用于垃圾收集。

(有趣的是,当使用反射器查看编译后的代码时,似乎有或没有附加大括号没有区别)

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

【问题讨论】:

    标签: c# vb.net scope reflector


    【解决方案1】:

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

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

    If True Then
       Dim y As New [myClass]()
       y.MyProperty = 2000
       Console.WriteLine("y = " & y.MyProperty)
    End If
    

    作为限制范围的一种方式。我很惊讶它会困扰记住paintballbob's answer

    【讨论】:

      【解决方案2】:

      似乎没有在 vb 中创建新范围的好方法,但您可以创建一个只运行一次的循环,然后在该循​​环中声明您的变量。

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

      即使变量的范围被限制在一个块中,它的生命周期仍然是整个过程的生命周期。如果在过程中多次输入块,则每个块变量都保留其先前的值。为了避免在这种情况下出现意外结果,明智的做法是在块的开头初始化块变量。

      源代码:http://msdn.microsoft.com/en-us/library/1t0wsc67.aspx

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

      【讨论】:

      • 您对范围和生命周期的看法是正确的。仅在程序完成后才发生垃圾收集并不完全正确。它可能会更早发生,请参阅 Skeet 的回答。
      【解决方案3】:

      至少在 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 会更加保守,因为您可能希望在变量的最后一个“正常”读取点之后检查变量的值。

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

      除了作用域之外,我不知道 VB 是否有任何等效的语句块;最接近的等价物可能是With 语句...或Do ...Loop While False 语句,两者都不完全令人满意。

      【讨论】:

      • 关于范围,.Net 帮助提到 With 块定义了块级别的范围,它适用于块内定义的任何内容,但不适用于块的主题。可以通过使用 With 1 end with 或 With True End With 来缩小范围,但它仍然感觉很糟糕......
      • GC 行为在 VB.NET 中是相同的。 VB.NET 没有等效于范围的语句块 - 请参阅 MSDN 条目(来自paintballbob 的回答)msdn.microsoft.com/en-us/library/1t0wsc67.aspx
      【解决方案4】:

      为什么不只创建几个方法呢?范围应该在方法中定义。退出该方法后,您将离开范围 - 干净且简单。您的做法非常不正统 - 如果您担心范围蔓延(您所描述的),我建议您坚持约定并使用方法。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2022-10-25
        • 2015-06-09
        • 2019-07-07
        • 1970-01-01
        • 2020-01-16
        • 2015-07-16
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多