namespace MyNameSpace
{
static class MyClass
{
static MyClass()
{
//Authentication process.. User needs to enter password
}
public static void MyMethod()
{
//Depends on successful completion of constructor
}
}
class Program
{
static void Main(string[] args)
{
MyClass.MyMethod();
}
}
}
これが私が想定したシーケンスです
さて、どのシナリオでも、4が2の前に開始する場合、私はねじ込まれています。出来ますか?
ここでは1つの質問しかしませんでしたが、質問は12か所ほどありますする必要がありますなので、すべてお答えします。
これが私が想定したシーケンスです
cctor
とも呼ばれます)これは正しいです?
いいえ。正しい順序は次のとおりです。
静的フィールド初期化子がある場合はどうなりますか?
CLRは、静的フィールド初期化子が実行される順序を変更できる場合があります。詳細については、件名に関するJonのページを参照してください。
そのクラスのcctorが完了する前に
MyMethod
のような静的メソッドが呼び出される可能性はありますか?
はい。 cctor自体がMyMethodを呼び出す場合、明らかにcctorが完了する前にMyMethodが呼び出されます。
CctorはMyMethodを呼び出しません。 MyClassのcctorが完了する前に
MyMethod
のような静的メソッドを呼び出すことは可能ですか?
はい。 cctorが別の型を使用し、そのcctorがMyMethodを呼び出す場合、MyClass cctorが完了する前にMyMethodが呼び出されます。
直接または間接的にMyMethodを呼び出すcctorはありません! MyClassのcctorが完了する前に
MyMethod
のような静的メソッドを呼び出すことは可能ですか?
番号。
複数のスレッドが関係していても、それは本当ですか?
はい。 cctorは、静的メソッドが任意のスレッドで呼び出される前に、1つのスレッドで終了します。
Cctorを複数回呼び出すことはできますか? 2つのスレッドが両方ともcctorを実行するとします。
関係するスレッドの数に関係なく、cctorは最大で1回呼び出されることが保証されています。 2つのスレッドが「同時に」MyMethodを呼び出すと、競合します。それらの1つはレースに敗れ、MyClass cctorが勝者のスレッドで完了するまでブロックします。
失われたスレッドblocks cctorが完了するまで? 本当に?
本当に。
では、winningスレッドのcctorが、以前にlosingスレッドが取得したロックをブロックするコードを呼び出すとどうなるでしょうか。
次に、古典的なロック順序反転条件があります。プログラムのデッドロック。永遠に。
危険そうです。デッドロックを回避するにはどうすればよいですか?
あなたがそれをするときにそれが痛いなら、-それをやめる。 cctorでブロックできるようなことをしないでください
複雑なセキュリティ要件を強制するためにcctorの初期化セマンティクスに依存することは良い考えですか?そして、ユーザーとの対話を行うcctorを用意するのは良い考えでしょうか?
どちらも良いアイデアではありません。私のアドバイスは、メソッドのセキュリティに影響を与える前提条件が満たされていることを確認する別の方法を見つける必要があるということです。
[〜#〜] msdn [〜#〜] によると、静的コンストラクタ:
最初のインスタンスが作成される前、または静的メンバーが参照される前に、静的コンストラクターが自動的に呼び出されてクラスを初期化します。
したがって、静的コンストラクターは、静的メソッドMyClass.MyMethod()
が呼び出される前に呼び出されます(も呼び出されない静的構築または静的フィールドの初期化中に呼び出されます)もちろん)。
ここで、非同期で何かをしている場合、static constructor
、それを同期するのはあなたの仕事です。
#3は実際には#1です。静的な初期化は、それが属するクラスが最初に使用されるまで開始されません。
MyMethod
が静的コンストラクターまたは静的初期化ブロックから呼び出された場合、それは可能です。静的コンストラクターから直接または間接的にMyMethod
を呼び出さない場合は、問題ありません。
documentation (私の強調)から:
静的コンストラクターが自動的に呼び出され、クラスを初期化します最初のインスタンスの前が作成されますまたは静的メンバーが参照されます。
4が常に2の後に来ることを保証できます(静的メソッドからクラスのインスタンスを作成しない場合)。ただし、1と3には同じことが当てはまりません。
静的コンストラクターは、mymethodが実行される前に呼び出されます。ただし、4が2の前に呼び出された場合にねじ込まれている場合は、設計を再考することをお勧めします。とにかく静的コンストラクタで複雑なことをするべきではありません。
CLRは、静的メンバーがアクセスされる前に静的コンストラクターが実行されることを保証します。ただし、デザインは少し臭いです。次のようなことをするほうが簡単です:
static void Main(string[] args)
{
bool userIsAuthenticated = MyClass.AuthenticateUser();
if (userIsAuthenticated)
MyClass.MyMethod();
}
設計上、認証が失敗した場合、MyMethodが実行されないようにする唯一の方法は、例外をスローすることです。
メソッドが実行される前に、静的クラスのコンストラクターが呼び出されていることが保証されます。例:
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Press enter");
Console.ReadLine();
Boop.SayHi();
Boop.SayHi();
Console.ReadLine();
}
}
static class Boop
{
static Boop()
{
Console.WriteLine("Hi incoming ...");
}
public static void SayHi()
{
Console.WriteLine("Hi there!");
}
}
出力:
Enterキーを押します
// Enterキーを押した後
こんにちは...
こんにちは!
こんにちは!
以下に、実際の順序を示します。
Main
の開始MyClass
コンストラクタの開始MyClass
コンストラクターの終わりMyMethod
の開始Main
の終わりまたは、デバッガーをステップ実行できます。