2008-09-17 12 views
10

C#では、他のステートメントに添付されていないメソッド内でブロックを作成することができます。C#で匿名の非結合ブロックの値は何ですか?

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

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

このコードは、メインメソッド内のカッコが存在しないかのようにコンパイルされて実行されます。ブロック内のブロックにも注意してください。

これが貴重なシナリオはありますか?私はまだ何も発見していないが、他の人々の知見を聞いて興味がある。

答えて

11

スコープとガベージコレクション:ブロックされていないブロックを離れると、その中に宣言されている変数は範囲外になります。これにより、ガベージコレクタはそれらのオブジェクトをクリーンアップすることができます。

Ray Hayesは、.NETガベージコレクタが範囲外のオブジェクトをすぐに収集しないことを指摘しているため、スコープが主な利点です。

+1

これは実際にVMレベルで確認しましたか?最も合理的なコンパイラとGCは、コンパイルプロセス中に2つのブロックを1つにまとめる傾向があり、それを参照する変数を最後に使用した後にGCに値を渡すことができます。 – emk

+0

私はガベージコレクションを検証していませんが、範囲を確認しました。私はかなり.NETのガーベジコレクターが範囲を残したものを収集する/参照されていないと確信しています。 –

+2

GCが起動する可能性がありますが、それはしばらくお待ちください!範囲の喪失は自動GCを意味しません。また、この場合、値型の場合、GCには何もありませんでした。 GCではなくスコープが主な目的です。 –

1

私が見る限り、それは組織的な観点からのみ役立つだろう。私はそれを行う上で論理的な価値を考え出すことはできません。おそらく誰かが適切な例を持っているでしょう。

0

これを行う理由の1つは、変数 'z'と 'zz'がその内部ブロックの終わりより下にコーディングすることができないことです。 Javaでこれを行うと、JVMは内部コード用のスタックフレームをプッシュし、それらの値はスタックに格納されます。コードがブロックを終了すると、スタックフレームがポップされ、それらの値は消えます。関係するタイプに応じて、ヒープやガベージコレクションを使用する必要がなくなります。

3

これは、パーサールールの副産物であり、そのステートメントは単純なステートメントまたはブロックのいずれかです。すなわち、単一のステートメントができる場合はいつでもブロックを使用することができる。

if (someCondition) 
SimpleStatement(); 

if (SomeCondition) 
{ 
    BlockOfStatements(); 
} 

他の人は、変数宣言が包含ブロックの終わりまで範囲内にあることを指摘しています。一時的な変数のスコープが狭いのは良いことですが、変数のスコープを制限するためにブロックを使用する必要はありませんでした。時には "using"ステートメントの下のブロックを使用することもあります。

だから一般的には価値がありません。

0

C# - like c/C++/java - bracesはスコープを表します。これは変数の存続期間を指定します。閉じ括弧に達すると、変数はガベージコレクションのためにすぐに利用可能になります。 C++では、varがインスタンスを表す場合、クラスのデストラクタが呼び出されます。

使用方法は、大きなオブジェクトを解放することだけですが、tbhをnullに設定すると同じ効果があります。私は以前の使用法はおそらく、C++プログラマが管理されたコードに親しみやすく快適な領域でいくらか移動するようにすることだと考えています。本当にC#で "デストラクタ"を呼び出す場合は、通常はIDisposableインターフェイスを実装し、 "using(var){...}"パターンを使用します。

Oisin

0

は、それが何らかの理由(例えば、変数のスコープ制御)のために実際に有用であったとしても、私は古き良きコードreadibilityの観点から、そのような構築物からあなたを落胆ます。

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

私は今考えることができる唯一のことは、EXAのためでありますいくつかの大きなオブジェクトを処理していて、その中からいくつかの情報を抽出した後で、一連の操作を実行しようとすると、大きなオブジェクト処理をブロックに入れて範囲外にすることができます。

{ 
     //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 
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); 
    } 
... 

これはまた、あなたとラベルのために働くことができます。

1

実際に存在する理由の1つは、ブロックの他の理由を導入する必要がないときに変数の範囲を制限したい場合です。実際には、これは事実上決して有用ではありません。

個人的には、言語/コンパイラの観点から、ステートメントが予想される場所にブロックを置くことは簡単だと思っています。それはif/for/method宣言などなし。

Eric Lippertの最初のthis recent blog postを考えてみましょう。 ifステートメントの後に単一のステートメントまたは中括弧で囲まれたいくつかのステートメントの後には、単に単一のステートメントが続いています。中括弧で囲まれた0のN個のステートメントを0にすると、(言語パーサの観点から見れば)そのコードセクションが1つのステートメントになります。この同じ習慣はすべてのループ構造にも当てはまりますが、ブログ記事の要点は説明していますが、try/catch/finallyブロックには適用されません。

その観点からブロックをアドレッシングすると、「1つのステートメントを使用できる場所でブロックが使用されないようにする魅力的な理由はありますか?答えは「いいえ」です。

関連する問題