Nir
Nir

Reputation: 4013

Getter property is run without anyone calling it

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

Upvotes: 3

Views: 497

Answers (4)

Marc Gravell
Marc Gravell

Reputation: 1062915

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.

Upvotes: 1

Will Vousden
Will Vousden

Reputation: 33358

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

Upvotes: 1

Jon Skeet
Jon Skeet

Reputation: 1500835

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.

Upvotes: 9

Matthew Steeples
Matthew Steeples

Reputation: 8058

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?

Upvotes: 2

Related Questions