0
public class ModelInfo
{
    public int AssignedCount { get; set; }
    public int UnassignedCount { get; set; }
    public int TotalCount { get { return UnassignedCount + TotalCount; } }
}

*編集: * このコードを SO に入れると、TotalCount プロパティが UnassignedCount + TotalCount を追加していることに気付きました (他の 2 つのカウントを一緒に追加するつもりでした)。SOエラーが発生する理由について、誰かが完全な説明を提供してもらえますか? つまり、低レベルのもの。

スタックオーバーフロー!

4

9 に答える 9

13

TotalCount内から呼び出しTotalCountています。そうしないでください。

代わりに、プロパティの値用に別のフィールドを使用できます。

ただし、コードは次のように読む必要があると思います。

public int TotalCount { get { return UnassignedCount + AssignedCount ; } }

編集:スタックオーバーフローが発生する理由については、プロパティを使用しているときに、.NET コンパイラが実際に 2 つの関数を生成しset_PropertyNameget_PropertyName. したがって、本質的には、get_PropertyName無限に深くなるメソッド呼び出しからスタックオーバーフローが発生します。

于 2012-08-22T20:39:37.560 に答える
4

何が起こっているかを確認する最も簡単な方法 (IMO) は、これらのプロパティをメソッドに変換することです。

// If we didn't have properties, this is what the two first lines would be. Ick!
private int assignedCount;
private int unassignedCount;

public int GetAssignedCount()
{
    return assignedCount;
}

public void SetAssignedCount(int value)
{
    assignedCount = value;
}

public int GetUnassignedCount()
{
    return unassignedCount;
}

public void SetUnassignedCount(int value)
{
    unssignedCount = value;
}

// And here's the read-only TotalCount property translation
public int GetTotalCount()
{
    return GetUnassignedCount() + GetTotalCount();
}

これで、内部の再帰GetTotalCount()が非常に明確になるはずです。メソッドは無条件に自分自身を呼び出すため、最終的にはスタックを爆破します。

自動実装されたプロパティの混合と、プロパティ アクセスがフィールド アクセスのように見えるという事実は、それらが実際には偽装されたメソッドであることを思い出すのを妨げることがあります。上記の翻訳ですべてがより明確になることを願っています。

于 2012-08-22T20:43:33.440 に答える
3

SOエラーが発生する理由について、誰かが完全な説明を提供してもらえますか?

確かに: を計算するためにTotalCount、コンパイラは次のようなコードを生成します。

  • 得るUnassignedCount
  • 得るTotalCount
  • UnassignedCountに追加TotalCount
  • 結果を返す

のプロパティ getter を呼び出すとTotalCount(getter は特別な構文を使用する通常の引数のない関数であることを思い出してください)、ランタイムは戻りアドレスをスタックに配置します。2 番目のステップでは、スタック上に 1 つの余分なリターン アドレスを使用して最初に戻ります。3 番目のステップでもう一度実行し、次に 4 番目、5 番目、というように続きます。呼び出しごとに、別の戻りアドレスがスタックに置かれます。これはスタックの限界まで続き、その時点で例外がスローされます。

于 2012-08-22T20:43:25.257 に答える
2

これを書くことができるはずです: TotalCount を設定することはできないため、値がないことに注意してください。おそらくこれを行うつもりでしたか:

public class ModelInfo
{
    public int AssignedCount { get; set; }
    public int UnassignedCount { get; set; }
    public int TotalCount { get { return UnassignedCount + AssignedCount; } }
}
于 2012-08-22T20:47:49.580 に答える
1

ネストされた呼び出しを追跡するために使用される「スタック」と呼ばれるメカニズムがあります。メソッドまたは関数を呼び出すと、現在の「スタック フレーム」 (呼び出したメソッドが戻るときに制御が転送されるアドレス、およびメソッド内のパラメーターとメソッド ローカル) がスタックにプッシュされます。制御がメソッドに戻ると、このスタック フレームが取り除かれ、CPU レジスタが以前の状態に復元されるため、メソッドの実行を継続できます。

スタックはメモリの固定割り当てであるため、関数が返されたときに CPU レジスタの状態を復元するために必要な情報を格納する場所がなくなる前に、多くのレベルを呼び出すことができます。この時点で、スタックがオーバーフローしたため、スタック オーバーフロー エラーが発生します。あまりにも多くのネストされた呼び出しを行ったため、それらを記録するためのメモリが不足しました。

そのため、例外が発生します。無限に再帰します。プロパティ ゲッターは、スタックに空きがなくなるまで何度も何度も自分自身を呼び出します。

于 2012-08-22T20:43:12.283 に答える
0

ゲッターTotalCount内で参照しているためです。TotalCountスタック オーバーフローに達するまで、無限ループが発生します。

于 2012-08-22T20:40:20.670 に答える
0

の値を取得しようとすると、ぐるぐるループしていますTotalCount

大まかに言うと、TotalCount を取得するロジックは次のとおりです。

  • UnassignedCount の値を取得する
  • Totalcount の値を取得する

繰り返し、すすぎ、洗います。

編集:理由については、Wikiをご覧ください

于 2012-08-22T20:40:56.927 に答える
0

あなたは無限再帰、それ自体を呼び出すプロパティにいます

于 2012-08-22T20:41:09.463 に答える
0

コール スタックが (理論的には) 無限に深くなるからです。また、必要なすべてのデータを保持するための無限のスタックはありません。

于 2012-08-22T20:41:31.350 に答える