質問

私は.NET 3.5で働いています。スタックとゲッタープロパティを備えたクラス「A」があり、呼び出された場合、スタック内の最初のアイテムを削除し、次のアイテムを取得します。

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

プロパティを関数に変更すると、スタックはOKに戻ります。

なぜそうなのかを誰かが説明できれば幸せです。

これが簡素化されたクラスです:

 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(); 
            };
        }            
    }
役に立ちましたか?

解決

第一に、プロパティアクセサを変更することは、一般的に悪い考えです。それがすべきことは、何かをゆっくりと初期化することです - または、おそらく揮発性の価値を与えることです( DateTime.Now します)。

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

他のヒント

Urls.Pop();

なりたい

return Urls.Pop();

値を返すとき 同時にリストから削除します


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

これは悪いデザインだと思います。 GETアクセサは、後続の呼び出しで異なる結果をもたらす方法でオブジェクトを変異させないでください。

IMO、ここでの問題は、非自明な副作用を持つプロパティを持っていることです。これは方法でなければなりません:

    public string GetNextUrl() { /* */ }

それ以外の場合、悪いことがどこでも起こります(デバッガー、データバインディングなど)。誰かが一度しか財産を読んでいると仮定しないでください。

プロパティでの副作用の唯一の賢明な使用は、怠zyなロード、繰り延べられた初期化などです。他の明らかな変異呼び出しなしで順次呼び出された場合、同じ値を報告する必要があります。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top