C#中的匿名未添加块的值是什么?

时间:2020-03-05 18:59:23  来源:igfitidea点击:

在C中,我们可以在未添加到任何其他语句的方法内部制作块。

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

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

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

在某种情况下这将是有价值的吗?我还没有找到任何东西,但很好奇听到别人的发现。

解决方案

回答

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

回答

范围和垃圾回收:当我们离开未添加的块时,其中声明的任何变量都将超出范围。这样垃圾收集器就可以清理那些对象。

雷·海斯(Ray Hayes)指出,.NET垃圾收集器不会立即收集范围外的对象,因此范围界定是主要优点。

回答

这样做的原因之一是变量" z"和" zz"在该内部块的末尾将无法进行编码。当我们使用Java进行此操作时,JVM会为内部代码推送一个堆栈框架,并且这些值可以存在于堆栈中。当代码退出该块时,将弹出堆栈框架,而这些值将消失。根据所涉及的类型,这可以使我们不必使用堆和/或者垃圾收集。

回答

这是解析器规则的副产品,即语句是简单语句还是块。即在任何一条语句可以使用的任何地方都可以使用一个块。

例如

if (someCondition)
 SimpleStatement();

if (SomeCondition)
{
   BlockOfStatements();
}

其他人指出,变量声明的作用域一直到包含块的末尾。临时var的作用域较短是很好的选择,但我从来不需要自己使用块来限制变量的作用域。有时,我们可以在"使用"语句下面使用一个块。

因此,通常它没有价值。

回答

在类似C / c ++ / java的括号中,括号表示范围。这决定了变量的寿命。当到达右括号时,该变量将立即可用于垃圾回收。在c ++中,如果var表示实例,则将导致调用类的析构函数。

至于用法,唯一可能的用途是释放一个大对象,但是将tbh设置为null会产生相同的效果。我怀疑以前的用法可能只是为了使C ++程序员在熟悉和舒适的范围内转移到托管代码。如果确实要在c#中调用"析构函数",则通常要实现IDisposable接口并使用" using(var){...}"模式。

爱信

回答

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

回答

除了语义之外,对于范围和垃圾回收来说,这没有任何价值,在这个有限的示例中,它们都不重要。如果我们认为它可以为我们自己和/或者其他人使代码更清晰,那么我们肯定可以使用它。但是,在代码中用于语义澄清的更普遍接受的约定通常只在选项内嵌注释中使用换行符:

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;
}

回答

例如,如果我们想重用变量名,通常就不能重用变量名。
这是无效的

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

回答

这使我们可以在任何地方创建作用域块。它本身并没有那么有用,但是可以使逻辑更简单:

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
 ...

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

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#中使用它们。