C#中匿名未附加块的价值是多少?

时间:2008-09-17 16:54:05

标签: c#

在C#中,你可以在一个没有附加到任何其他语句的方法中创建一个块。

    public void TestMethod()
    {
        {
            string x = "test";
            string y = x;

            {
                int z = 42;
                int zz = z;
            }
        }
    }

此代码编译并运行,就好像main方法中的大括号不在那里一样。还要注意块内的块。

是否存在有价值的情况?我还没有找到,但我很想知道其他人的发现。

10 个答案:

答案 0 :(得分:11)

范围和垃圾收集:当您离开未连接的块时,其中声明的任何变量都超出范围。这让垃圾收集器可以清理这些对象。

Ray Hayes指出.NET垃圾收集器不会立即收集超出范围的对象,因此范围界定是主要的好处。

答案 1 :(得分:4)

例如,如果要重用变量名,通常不能重用变量名 这是无效的

        int a = 10;
        Console.WriteLine(a);

        int a = 20;
        Console.WriteLine(a);

但这是:

    {
        int a = 10;
        Console.WriteLine(a);
    }
    {
        int a = 20;
        Console.WriteLine(a);
    }

我现在唯一可以想到的,例如,如果你正在处理一些大型对象,并从中提取出一些信息,之后你将要执行一系列操作,你可以把块中的大对象处理,使其超出范围,然后继续其他操作

    {
        //Process a large object and extract some data
    }
    //large object is out of scope here and will be garbage collected, 
    //you can now perform other operations with the extracted data that can take a long time, 
    //without holding the large object in memory

    //do processing with extracted data

答案 2 :(得分:3)

它是解析器规则的副产品,该语句是简单语句或块。即,只要单个语句可以使用块,就可以使用。

e.g。

if (someCondition)
 SimpleStatement();

if (SomeCondition)
{
   BlockOfStatements();
}

其他人已指出变量声明在范围内,直到包含块结束。临时变量具有短范围是有好处的,但我从来不必使用它自己的块来限制变量的范围。有时你会在“using”语句下面使用一个块。

所以一般来说它没有价值。

答案 3 :(得分:1)

据我所知,从组织的角度来看,这只是有用的。我无法真正想到这样做的任何逻辑价值。也许有人会有一个恰当的例子。

答案 4 :(得分:1)

这允许您在任何地方创建范围块。它本身并没有那么有用,但可以使逻辑更简单:

switch( value )
{
    case const1: 
        int i = GetValueSomeHow();
        //do something
        return i.ToString();

    case const2:
        int i = GetADifferentValue();
        //this will throw an exception - i is already declared
 ...

在C#中,我们可以使用范围块,以便在每种情况下声明的项目仅在范围内:

switch( value )
{
    case const1: 
    {
        int i = GetValueSomeHow();
        //do something
        return i.ToString();
    }

    case const2:
    {
        int i = GetADifferentValue();
        //no exception now
        return SomeFunctionOfInt( i );
    }
 ...

这也适用于gotos和标签,而不是你经常在C#中使用它们。

答案 5 :(得分:1)

它存在的一个实际原因是,如果你想要在没有引人注目的需要引入任何其他原因的情况下限制某些变量的范围。在实际操作中,这实际上从未有用。

就我个人而言,我的猜测是,从语言/编译器的角度来看,你可以更容易地说你可以把一个块放在预期的语句的任何地方,而且他们根本就没有竭尽全力阻止你使用它没有if / for /方法声明/ etc。

考虑Eric Lippert的开头this recent blog postif语句后面没有单个语句或大括号括起来的一些语句,后面只跟一个语句。无论何时用花括号括起0到N个语句,你都可以使这段代码等同于(从语言分析器的角度来看)一个语句。同样的做法同样适用于所有循环结构,虽然博客文章的主要内容解释说,它不适用于try / catch / finally块。

当从那个角度解决块时,问题就变成了,“是否有令人信服的理由阻止在可以使用单个语句的任何地方使用块?”答案是,“不”。

答案 6 :(得分:0)

这样做的一个原因是变量'z'和'zz'不能用于该内部块末尾下面的代码。当您在Java中执行此操作时,JVM会为内部代码推送堆栈帧,并且这些值可以存在于堆栈中。当代码退出块时,会弹出堆栈帧并且这些值消失。根据所涉及的类型,这可以使您不必使用堆和/或垃圾回收。

答案 7 :(得分:0)

在C#中 - 像c / c ++ / java - braces表示范围。这决定了变量的生命周期。当到达右括号时,变量立即可用于垃圾收集。在c ++中,如果var表示一个实例,它将导致调用类的析构函数。

至于用法,唯一可能的用途是释放一个大对象但是tbh,将它设置为null会产生相同的效果。我怀疑之前的用法可能只是为了让c ++程序员在熟悉和舒适的领域中转向托管代码。如果真的想在c#中调用“析构函数”,通常会实现IDisposable接口并使用“using(var){...}”模式。

[287]莪

答案 8 :(得分:0)

即使它出于任何原因(例如变量范围控制)实际上是有用的,但从良好的旧代码可读性的角度来看,我会劝阻你不要使用这种结构。

答案 9 :(得分:0)

除了语义和范围和垃圾收集之外,没有任何其他值,在这个有限的例子中没有一个是重要的。如果您认为它使代码更清晰,对于您自己和/或其他人,那么您当然可以使用它。但是,代码中更为公认的语义澄清约定通常只使用换行符在线注释:

public void TestMethod()
{
    //do something with some strings
    string x = "test";
    string y = x;

    //do something else with some ints
    int z = 42;
    int zz = z;
}