2

I am new to C# and am exploring the very basic of C# get and set properties. What I have found is, The get set accessor or modifier mostly used for storing and retrieving value from the private field.

In this case, What is the problem with using public fields?

Another thing, I have written some conditions inside get and set. The code is

public int Number
    {
        get
        {
            if(Number>10)return 10;
            else
            {
                return Number;
            }
        }
        set
        {
            if (value > 10)
            {
                Number = 10;
            }
            else
            {
                Number = value;
            }                   
        }
    }

Whats the problem here?

And another interesting thing is, in VS, the recursive sign appears where I check the conditions.Can someone explain it, please?

enter image description here

I am new to C# and wants to learn from the basic. Thanks in advance.

Noor A Shuvo
  • 2,639
  • 3
  • 23
  • 48
  • https://www.google.fr/?gws_rd=ssl#q=What+is+the+problem+with+using+public+fields – Joe Feb 17 '17 at 17:50
  • 1
    Whats the problem here? None for what I see, does it throw any exception or it doesn't works as expected? – Gusman Feb 17 '17 at 17:50
  • 1
    Have you looked at the [documentation](https://msdn.microsoft.com/en-us/library/x9fsa0sw.aspx) and [tutorials](https://msdn.microsoft.com/en-us/library/aa288470(v=vs.71).aspx)? – clcto Feb 17 '17 at 17:51
  • 1
    1. *you* need to tell what the problem is, by including compiler or runtime error information. general reference and documentation on properties in C# is available [all](http://stackoverflow.com/questions/5096926/what-is-the-get-set-syntax-in-c) [over](https://msdn.microsoft.com/en-us/library/w86s7x04.aspx) [the place](http://stackoverflow.com/questions/4662442/c-sharp-get-set-syntax-usage) 2. the recursion occurs because you reference the `Number` property from within its accessors. – Cee McSharpface Feb 17 '17 at 17:51
  • The problem was stackOverflow exception. Now I got it why we use get and set. Thanks! – Noor A Shuvo Feb 17 '17 at 18:03

4 Answers4

9

Initial Problem - StackOverflow

The problem is that you are inadvertently using recursion, which is going to lead to a stack overflow, because your getters and setters for the Number property are getting and setting the Number property, rather than a backing field.

It should at the very least be changed to this:

private int number;

public int Number
{
    get
    {
        if(this.number>10)return 10;
        else
        {
            return this.number;
        }
    }
    set
    {
        if (value > 10)
        {
            this.number = 10;
        }
        else
        {
            this.number = value;
        }                   
    }
}
Seth Flowers
  • 8,990
  • 2
  • 29
  • 42
  • Note that the "this." here is not necessary, e.g., I prefer "return number;". – Polyfun Feb 17 '17 at 17:56
  • I know, though I prefer `this`. StyleCop required it (at least a while ago). It makes it obvious that it is scoped to the class rather than scoped to the method/property, etc. – Seth Flowers Feb 17 '17 at 17:58
  • @sethflowers An alternative is to adopt specific naming conventions for class fields, such as prefixing them with an underscore (`_number`) or in my company's case, a lower-case m (`mNumber`). – Kyle Feb 17 '17 at 19:15
  • @Kyle - True - but while those work, I don't like either. I prefer `this` over an underscore. As for Hungarian notation - it only makes sense if you can't tell the type from the name, which is the wrong problem to solve. – Seth Flowers Feb 17 '17 at 19:45
2

You are missing a private backing field. Your property is self-referencing (hence the recursion symbol).

Try this instead:

private int _number;

public int Number
{
    get
    {
        if(_number > 10)
        {
            return 10;
        }
        else
        {
            return _number;
        }
    }
    set
    {
        if (value > 10)
        {
            _number = 10;
        }
        else
        {
            _number = value;
        }                   
    }
} 
Silas Reinagel
  • 4,155
  • 1
  • 21
  • 28
1

As far as I can tell you are calling the Number several times inside your code. And the recursive loop will run forever until it runs into a StackOverflow :)

I ran your code with :

 this.Number = 100;
 int num = this.Number;

Basically this should trigger the setter and the getter. When the if clause is setting the number to 10, the first recursion is entered since you are setting the number again. It will try to set the number to 10 recursively by Number=10

Add a backing field above number, like this:

private int number; // Backing field
public int Number
{
    get { return number; }  // Getter
    set { number = value; } // Setter
}
kacie_23
  • 116
  • 1
  • 7
1

The main idea of a property with public read/write access is to simply be a mutator and accessor for the internal state of their containing object.

When you have conditional logic inside these get/set methods their "contract" with consumers of the class is being broken....when I call the accessor/getter

var number = anInstance.Number;

...I expect to receive the current state of the anInstance object's number, not some logic-driven derivative of it. Similarly for the Mutator/setter

anInstance.Number = 123;

...I expect that to automatically set the internal state of the anInstance object's number.

If i set the Number in one statement...

anInstance.Number = 123; // I expect anInstance to have an internal state of 123 for it's Number
var x = anInstance.Number; // I expect 123 back, not 10

...if I then retrieve that value on the next line, I expect the same value back, but with your current implementation (if it wasn't also recursive - see below), when I set Number to 123, this is being ignored and the value of 10 is saved as the new internal state and when I then retrieve Number I would get back a value of 10.

It is not the concern of the Number property to be changing what the caller has requested be set as it's value. An invoker of the Number property rightly expects it's instructions to be followed and the invoker shouldn't have to know about weird internal getter-setter logic in order to function.

If you really need to get/set things in a conditional way, the place for the conditional logic is outside the class containing the Number property, i.e. replace the Number property with a simple auto-implement getter-setter and use in the following way.

int x = anInstance.Number > 10 ? 10 : anInstance.Number; // replaced getter logic outside the class containing the `Number` property
anInstance.Number = x > 10 ? 10 : x; // replaced setter logic

As for the reason why you are seeing the recursion symbol, that is because your code is recursively calling itself. The Number property is calling itself, instead of some backing field. Change the property to be like...

private int number;
public int Number
{
    get
    {
        return number; // note the lower-case 'n' refers to the private field instead of the property
    }
    set
    {
        number = value;
    }
}

Note, though, that there is no need to have a private backing field when you use your property in this simple way. If the intent is to have full read-write access, you could simply use a public field.

public int Number;

However, a property allows you to control access to fields, e.g.

public int Number { get; private set; }

which a simple public property does not allow, although you can use the readonly modifier to give this behaviour.

public readonly int Number;

However, another advantage of using a property over using a field is that it can offer greater control over how internal state is used/stored, e.g.this example is taken from MSDN

class TimePeriod
{
    private double seconds;

    public double Hours
    {
        get { return seconds / 3600; }
        set { seconds = value * 3600; }
    }
}

In this example, the caller of this class' Hours property is getting and setting a value of hours but under the hood the internal state of the class is storing/retrieving using seconds. This would not be possible with a public field.

phil
  • 879
  • 1
  • 10
  • 20
  • Then, what will be the problem if I use public variable? What's the difference then between using a public field and using get set property of a private variable? – Noor A Shuvo Feb 17 '17 at 18:43