5

関数に静的変数があるとしましょう:

Private Sub SomeFunction()
    Static staticVar As String = _myField.Value
End Sub

_myFieldからの値がに代入されるのは、正確にはstaticVarいつですか? 関数への最初の呼び出し時?囲んでいるクラスのインスタンス化?

4

3 に答える 3

10

CLR はこの構造をサポートしていないため、VB.NET コンパイラはそれをエミュレートします。

創作第一。変数は、名前の競合が発生しないことを保証する不可解な名前を持つクラスのプライベート フィールドに持ち上げられます。変数がクラスのインスタンス メソッド内にある場合は、インスタンス フィールドになります。クラスのオブジェクトがnew演算子で作成されたときに作成されます。メソッドが Shared であるか、モジュールの一部である場合は、Shared フィールドになります。そのため、ジッターによってローダー ヒープに作成されます。

次の割り当ては、はるかに複雑な操作です。言語規則では、コードの実行が初めてDim ステートメントに到達したときに代入が発生します。初めてという用語は、ロードされたものです。これを保証するために、コンパイラによってメソッド内に大量のコードが生成されます。対処する必要がある問題の種類は、スレッド化、再帰、および例外です。

コンパイラは、変数の初期化状態を追跡するために、隠し変数フィールドと同じスコープでタイプStaticLocalInitFlagの別の隠しヘルパー フィールドを作成します。挿入されたコードの最初の部分は、スレッドを処理する Monitor.Enter() の呼び出しです。SyncLock と同じです。StaticLocalInitFlag はロック オブジェクトとして機能します。これが単なるブール値ではなくクラスであることに注意してください。

次に、Try ステートメントと Final ステートメントが例外を防ぎます。Try ステートメント内で、StaticLocalInitFlag.State の値が 0 かどうかがチェックされます。これにより、同じスレッドでの再帰から保護されます。その後、State は 2 に設定され、初期化コードが実行中であることを示します。続いて課題。次に、State がまだ 2 であるかどうかを再度チェックします。そうでない場合は、何かが大幅に間違っており、IncompleteInitialization 例外がスローされます。

次に、Finally ブロックは State を 1 に設定して、変数が初期化されたことを示します。Monitor.Leave() の呼び出しが続きます。

多くのコード、単純な変数のための 96 バイトの IL。コストを気にしない場合にのみ Static を使用してください。

于 2012-08-30T17:30:58.913 に答える
2

明らかに、Static変数は割り当てられるとインスタンス化されます。

その行が実行されるとき、前でも後でもありません。

それにブレークポイントを設定すると、表示されます。

Static呼び出し間で値が保持されることを意味します。

Sharedクラス/モジュールのメンバーは、クラスが初めてアクセスされたとき、Sharedコンストラクターの前、および呼び出しの前に、それがクラス コンストラクターまたは何らかのSharedメソッド/プロパティに対するものであるかどうかにかかわらず、インスタンス化されます。これがあなたの混乱の原因かもしれないと思います。C# のStaticlocal s のようなローカル変数は、この方法ではインスタンス化されません。static


Tim Schmelter からの興味深い情報です。値はShared、他のクラス レベル変数と同様にインスタンス化される非表示のクラス レベル変数を使用して内部的に維持されているようSharedですが、常にデフォルト値が使用されます。

クラスがアクセスされるときのインスタンス化の遅延を除いて、開発者が観察した効果は変更されていません。この遅延は、実際には検出できないはずです。

于 2012-08-30T15:05:26.537 に答える
1

VB.NET コンパイラは、"staticVar" の値を維持するために、静的な (VB.NET で共有される)クラスレベル変数を作成します。そのため、そのクラスの静的フィールドを最初に使用したとき (またはこのメソッドを呼び出したとき) に、他の静的/共有変数と同様に初期化されます。

http://weblogs.asp.net/psteele/pages/7717.aspx

于 2012-08-30T15:06:37.710 に答える