無限ループになって、アプリが落ちるプロパティのサンプル

2023年10月19日

プロパティの作り方、使い方

プロパティの値を取得する

次にコードをみてください。
これは正常に動作するでしょうか?

class MyClass
{
    public int Power
    {
        get
        {
            return Power;
        }
    }
}
class Program
{
    static void Main(string[] args)
    {
        MyClass myClass = new MyClass();
        Console.WriteLine(myClass.Power);
    }
}

実行結果

Process is terminating due to StackOverflowException.
翻訳)スタックオーバーフローの例外が原因でプロセスは終了しています。

プロパティは、クラスの外からは変数のようにアクセスができます。また、クラスの中からはメソッドのようにアクセスできます。
つまり

public int Power
{
    get
    {
        return Power;
    }
}

この部分は、クラスの中からは次のように記述されているのと同じような動きになるのです。

public int Power()
{
    return Power();
}

このようなコードを再帰といいます。これでは無限ループになるのでいいことは全くありませんが、無限ループにならないよう、breakする条件をつけること有用なコードとすることができるため、記述が禁止されているわけではありません。
メソッドは処理が終了した時点で呼び出し元に戻る必要があるため、呼び出し元のアドレスを都度スタックエリアに一時的に記録するので、このように無限にメソッドを呼び出すとスタックメモリがパンクしてオーバーフローになってしまうのです。

上のコードでは、イメージとして、

public int power;
public int Power()
{
    return power;
}

としたかったのですから、次のように書き換えることで問題なく実行できます。
大文字、小文字を注意深く確認してください。(C#では大文字、小文字は違うものとして扱います)

class MyClass
{
    // フィールド
    private int power;
    // プロパティ
    public int Power
    {
        get
        {
            return power;
        }
    }
}

自動プロパティ

C#3.0からは自動プロパティが使えるようになりました。
特にプロパティ内でコードを記述していなくても、プロパティとして利用する場合には、次のように簡略化することができます。

class MyClass
{
    // プロパティ
    public int Power { get; }
}

このコードだけ見ると最初の疑問のところと勘違いしそうですね。
実際には、コンパイラはこのコードを次のように変換して実行しています。

class MyClass
{
    // フィールド
    private int temp;
    // プロパティ
    public int Power
    {
        get
        {
            return temp;
        }
    }
}

tempフィールドは、コンパイラが内部で作って自身が使っているものです。
数値が代入されていない?
その通りです。フィールドの宣言で初期値が代入されていない場合、デフォルト値が設定されることになっています。ちなみにint型では、0が代入されています。

C#,入門

Posted by hidepon