9

誰かが私に印刷方法について質問しました

line no 1
line no 2
line no 3

読み取るメインメソッドを変更せずに

static void Main(string[] args)
{
    Console.WriteLine("line no 2");
}

ここでの 1 つのアプローチは、コンソール アプリケーションに複数のエントリ ポイントを用意することでした。ただし、次のような別のアプローチを試しました。

class Program
{
    [Some]
    static void Main(string[] args)
    {
        Console.WriteLine("line no 2");
    }
}
class SomeAttribute : Attribute
{
    public SomeAttribute()
    {
        Console.WriteLine("line no 1");
    }
    ~SomeAttribute()
    {
        Console.WriteLine("line no 3");
    }
}

各WriteLineにブレークポイントを適用すると、アプローチが機能していることがわかりますが、同じことがコンソールに反映されていません。

ちょっと興味があるんだけど。

4

3 に答える 3

15

Main問題は、コンソール アプリケーションのメソッド実行の前後にトリガーされるフックの検索に分解できます。

  • 最初のフックはProgram静的コンストラクターであり、クラスのメソッドのに実行されることが保証されています。 MainProgram

  • 2 番目は、「既定のアプリケーション ドメインの親プロセスが終了したときに発生するイベントProcessExit です。静的コンストラクターを使用して、このイベントをサブスクライブできます。AppDomain


class Program
{
    static Program()
    {
        Console.WriteLine("line no 1");

        AppDomain.CurrentDomain.ProcessExit += 
                                          (s, a) => Console.WriteLine("line no 3");
    }

    static void Main(string[] args)
    {
        Console.WriteLine("line no 2");
    }
}

プリント:

line no 1
line no 2
line no 3

次の部分はかなり長いものになります。SomeAttributeあなたの質問で何が問題なのかを説明しようと思います。

まず、この StackOverflow の質問を考慮して、カスタム属性コンストラクターがいつ実行されるかを正確に把握してください。一見しただけでは、これはそれほど単純ではありません。

すでにわかっているように、カスタム属性の ctor は、リフレクション経由でアクセスする場合にのみ実行されます。したがって、単純なプログラムの実行例では、属性コンストラクターはトリガーされません。SomeAttributeしかし、メソッドに適用すると、ブレークポイントがヒットするのはなぜMainですか? Visual Studio はリフレクションを使用して main メソッドを見つけ、デバッガーをアプリケーションにアタッチします。しかし、その時点ではコンソール ウィンドウはありません。したがって、ステートメントConsole.WriteLineは役に立たず、効果をもたらします。さらに、コンソール出力へのすべての次のステートメントをブロックしているようです。

したがって、次のコードは、VS デバッガーで実行するかどうかに応じて、異なる結果を生成します。

class Program
{
    [MyAttribute]
    static void Main()
    {

    }
}

class MyAttribute : Attribute
{
    public MyAttribute()
    {
        MessageBox.Show("MyAttribute ctor");
    } 
}

デバッガーなしで実行すると ( VS の既定の構成ではCtrl + F5 )、そのプログラムが終了し、ウィンドウが表示されないことがわかります。デバッガー ( F5 )で実行すると、次のように表示されます。

ここに画像の説明を入力

VSの横にコンソールウィンドウはなく、フォームアイコンのみを獲得します: ここに画像の説明を入力

前に説明したように、誰もいないときにコンソールに書き込もうとすると、他のすべての呼び出しはConsole.WriteLineコンソール アプリケーションに影響しません。そのため、コンストラクターでブレークポイントをステップ実行しても、コンソール メッセージを表示できます。

于 2013-04-13T11:08:23.470 に答える
6

Ilya Ivanovの答えがおそらく最良のものだと思います。ただし、私のものも面白い答えだと考えてください。

public class Program
{
    static Program()
    {
        Console.WriteLine("line no 1");
        Console.WriteLine("line no 2");
        Console.WriteLine("line no 3");
        Environment.Exit(0);
    }

    static void Main(string[] args)
    {
        Console.WriteLine("line no 2");
    }
}
于 2013-04-13T11:17:57.857 に答える