tags:

views:

159

answers:

4

I'm working in .net 3.5. I have a class "A" which has a stack and a getter property which, when called, removes the first item in the stack and retrieves the next one.

After initializing the class, I saw that the getter works without being called, and removes the top item in the stack, thus giving me bad results. A breakpoint in the getter did not show anyone passing through it.

When I change the property to a function, the stack is returned ok.

I'd be happy if someone could explain why is that.

Here is the simplified class:

 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(); 
            };
        }            
    }

Thanks!

+2  A: 
Urls.Pop();

wants to be

return Urls.Pop();

as it returns the value and removes it from the list at the same time


Actually having re-read your question, it looks like it is because the debugger evaluates properties. If you run the application without the debugger do you get the same problem?

Matthew Steeples
Yep, re re-reading, I guess you're right. Deleted my answer and lookings forward to the "disciplined" badge :-) +1
balpha
Haven't tried outside the debugger, but I'm almost 100% sure you're right. Thanks.
Nir
+7  A: 

Firstly, making a property accessor change the state is generally a bad idea. The most it should do is lazily initialize something - or possibly give a volatile value (like DateTime.Now does).

Secondly, you're probably seeing this if you're running under the debugger - it accesses properties while you're stepping through code. That would probably explain why the breakpoint wasn't being hit, too.

Jon Skeet
Thanks Jon. I'm honored. :)
Nir
+1  A: 

This is bad design I think. A get accessor should not mutate the object in a way that causes different results on subsequent calls.

Will Vousden
Thanks. Now I know that. :)
Nir
+1  A: 

IMO, the problem here is having a property that has non-obvious side-effects; this should be a method:

    public string GetNextUrl() { /* */ }

Otherwise bad things happen everywhere (the debugger, data-binding, etc). Don't assume that somebody only reads a property once.

The only sensible use of side-effects in properties is things like lazy-loading, deferred initialization, etc. It should still report the same value when called sequentially without any other obvious mutating calls.

Marc Gravell
Thanks, Marc. I appreciate it.
Nir