3

私は.net3.5で作業しています。スタックとgetterプロパティを持つクラス"A"があり、呼び出されると、スタックの最初のアイテムを削除して次のアイテムを取得します。

クラスを初期化した後、ゲッターが呼び出されずに機能し、スタックの最上位のアイテムが削除されるため、悪い結果が得られることがわかりました。ゲッターのブレークポイントは、それを通過する人を示していませんでした。

プロパティを関数に変更すると、スタックは正常に返されます。

誰かがその理由を説明してくれたら嬉しいです。

簡略化されたクラスは次のとおりです。

 public class A
    {
        private Stack<string> Urls;

        public A(string title, string[] array)
        {
            Urls = new Stack<string>();
            foreach (string s in array)
            {
                Urls.Push(s);
            }
        }

        public string Url
        {
            get { return Urls.Peek(); }
        }
        public string NextUrl
        {
            get{
            if (Urls.Count > 1)
                { Urls.Pop(); } 
            return Urls.Peek(); 
            };
        }            
    }
4

4 に答える 4

9

まず、プロパティアクセサーに状態を変更させることは、一般的に悪い考えです。それがすべきことのほとんどは、何かを怠惰に初期化することです-またはおそらく(DateTime.Nowそうするように)揮発性の値を与えることです。

次に、デバッガーで実行している場合は、おそらくこれが表示されます。デバッガーは、コードをステップ実行しているときにプロパティにアクセスします。それはおそらく、ブレークポイントがヒットされなかった理由も説明するでしょう。

于 2010-01-12T12:22:37.860 に答える
2
Urls.Pop();

になりたい

return Urls.Pop();

値を返すと同時にリストから削除するため


実際に質問を読み直したのは、デバッガーがプロパティを評価しているためのようです。デバッガーなしでアプリケーションを実行した場合、同じ問題が発生しますか?

于 2010-01-12T12:21:56.480 に答える
1

これは悪いデザインだと思います。getアクセサーは、後続の呼び出しで異なる結果を引き起こすような方法でオブジェクトを変更しないでください。

于 2010-01-12T12:23:29.227 に答える
1

IMO、ここでの問題は、明らかでない副作用を持つプロパティを持っていることです。これはメソッドである必要があります:

    public string GetNextUrl() { /* */ }

そうしないと、どこでも悪いことが起こります(デバッガー、データバインディングなど)。誰かがプロパティを一度だけ読み取ると思い込まないでください。

プロパティでの副作用の唯一の賢明な使用法は、遅延読み込み、遅延初期化などです。他の明らかな変更呼び出しなしで順次呼び出された場合でも、同じ値を報告する必要があります。

于 2010-01-12T12:23:47.870 に答える