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

これが私が仮定したシーケンスです

  1. 静的コンストラクターの開始
  2. 静的コンストラクターの終了
  3. メインの開始
  4. マイメソッドの始まり
  5. メインの終わり

4が2の前に開始される場合、どのシナリオでも、私はめちゃくちゃです。出来ますか?

4

10 に答える 10

220

ここで質問したのは1つだけですが、質問すべき質問が12ほどあるので、すべてに答えます。

これが私が想定したシーケンスです

  1. クラスコンストラクターの開始(別名cctor
  2. cctorの終わり
  3. メインの開始
  4. MyMethodの開始

これは正しいです?

いいえ。正しい順序は次のとおりです。

  1. プログラムのcctorがあれば、それを開始します。存在しない。
  2. プログラムのcctorがあれば、終了します。存在しない。
  3. メインの開始
  4. MyClassのcctorの開始
  5. MyClassのcctorの終わり
  6. MyClass.MyMethodの開始

静的フィールド初期化子がある場合はどうなりますか?

CLRは、静的フィールド初期化子が実行される順序を変更できる場合があります。詳細については、この件に関するJonのページを参照してください。

静的コンストラクターと型初期化子の違い

MyMethodそのクラスのcctorが完了する前に、のような静的メソッドが呼び出される可能性はありますか?

はい。cctor自体がMyMethodを呼び出す場合、cctorが完了する前に明らかにMyMethodが呼び出されます。

cctorはMyMethodを呼び出しません。MyMethodMyClassのcctorが完了する前に、のような静的メソッドが呼び出される可能性はありますか?

はい。cctorがMyMethodを呼び出す別のタイプを使用する場合、MyClasscctorが完了する前にMyMethodが呼び出されます。

直接または間接的に、MyMethodを呼び出すcctorはありません。MyMethodMyClassのcctorが完了する前に、このような静的メソッドを呼び出すことは可能ですか?

いいえ。

複数のスレッドが関係している場合でも、それはまだ当てはまりますか?

はい。cctorは、静的メソッドを任意のスレッドで呼び出す前に、1つのスレッドで終了します。

cctorを複数回呼び出すことはできますか?2つのスレッドの両方がcctorを実行させると仮定します。

関係するスレッドの数に関係なく、cctorは最大で1回呼び出されることが保証されています。2つのスレッドがMyMethodを「同時に」呼び出すと、それらは競合します。そのうちの1人はレースに負け、MyClasscctorが勝利スレッドで完了するまでブロックします。

cctorが完了するまで、失われたスレッドはブロックされますか?本当に

本当に。

では、勝ったスレッドのcctorが、負けたスレッドによって以前に取得されたロックをブロックするコードを呼び出した場合はどうなるでしょうか。

次に、古典的なロック順序の反転条件があります。プログラムがデッドロックします。永遠に。

それは危険なようです。どうすればデッドロックを回避できますか?

あなたがそれをするときにそれが痛いなら、それからそれをやめなさい。cctorでブロックできるようなことは絶対にしないでください。

複雑なセキュリティ要件を適用するためにcctor初期化セマンティクスに依存するのは良い考えですか?そして、ユーザーとの対話を行うcctorを用意するのは良い考えですか?

どちらも良い考えではありません。私のアドバイスは、メソッドのセキュリティに影響を与える前提条件が満たされていることを確認するための別の方法を見つける必要があるということです。

于 2012-02-22T16:38:46.200 に答える
11

#3は実際には#1です。静的初期化は、それが属するクラスが最初に使用されるまで開始されません。

MyMethodが静的コンストラクターまたは静的初期化ブロックから呼び出された場合に可能です。MyMethod静的コンストラクターから直接または間接的に呼び出さない場合は、問題ありません。

于 2012-02-22T16:13:18.507 に答える
2

メソッドが実行される前に、静的クラスのコンストラクターが呼び出されていることが保証されます。例:

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

出力:

エンターを押す

// エンターを押した後

こんにちは着信...

やあ!

やあ!

于 2012-02-22T16:18:33.233 に答える
2

The CLR guarantees that the static constructor runs before any static members are accessed. However, your design is a bit smelly. It would be more straightforward to do something like this:

static void Main(string[] args) 
{ 
     bool userIsAuthenticated = MyClass.AuthenticateUser();
     if (userIsAuthenticated)
         MyClass.MyMethod(); 
 } 

With your design, if authentication fails, the only way to prevent MyMethod from running is by throwing an exception.

于 2012-02-22T16:16:51.750 に答える
1

物事が下がる実際の順序は次のとおりです。

  1. 開始Main
  2. 静的MyClassコンストラクターの開始
  3. 静的MyClassコンストラクターの終了
  4. 開始MyMethod
  5. の終わりMain
于 2012-03-03T02:47:27.813 に答える
0

または、デバッガーでステップスルーすることもできます。

于 2012-02-29T19:49:48.077 に答える