Avoiding Property Recursion

This recently hit me on a project I was working on. Most people are familiar with property recursion:

public int Test { get { return this.test; } set { this.Test = value; } } private int test; 

You accidentally put an uppercase T in this setter, and you opened yourself up to a StackoverflowException . Worse, if you did not identify it, often the visual studio will automatically fix the case for you in an unacceptable condition.

I did something similar, but in the constructor recently:

 public TestClass(int test) { this.Test = Test; } 

Unfortunately, here you are not getting a StackOverflowException, now you have a programming error. In my case, this value was passed to the WebService, which instead used the default value (which was not 0), which made me skip the fact that I assigned it incorrectly. All integration tests passed because this service did not say

"Hey, you forgot this really important field!"

What steps can I take to avoid this behavior? I have always been advised not to define variables like the following, and I personally don’t like them, but I can’t come up with any other options:

 private int _test; private int mTest; 

EDIT

The reasons that the underscore or the prefix m is undesirable, as a rule, I can think of:

  • readability
  • It's a little harder to scroll through elements if you inherit from third-party classes when you get a combination of styles.
+47
c # properties recursion
Oct 30 '13 at 13:02
source share
5 answers

The best way is to use "Auto Implemented Properties" here.

 public int Test { get; set; } 

If it is not possible to use "Automatically implemented properties" for any reason, use the _ prefix (I do not prefer, though).

If you also do not prefer to use some prefixes, you have another option. You do not need to write property code manually. Let the IDE do it for you; this way you can avoid careless mistakes. (I don't know how I missed this in the original answer)

Just enter

 private int test; 

Select a field, right-click Refactor-> Encapsulate Field. The IDE will generate a property fragment for you, as shown below.

 public int Test { get { return test; } set { test = value; } } 

You do not need to worry about clicking the context menu. If you prefer a keyboard shortcut Ctrl + R + E.

Or get Resharper, it will immediately indicate your stupid mistake.

+62
Oct 30 '13 at 13:13
source share

Integration checks all past

Then they were not comprehensive enough. If there is an error that was not detected in the tests, you have another test to record.

This is truly the only automatic solution here. The compiler is not going to complain because the code is structurally and syntactically correct. It simply does not logically get fixed at runtime.

You can define naming standards, even use tools like StyleCop to try to enforce these standards. This will probably allow you to cover a lot, although this is not an ironclad solution, and errors can still go away. Personally, I agree with you that decorating variable names is unsightly in code. Perhaps in some cases this is a legitimate compromise?

Ultimately, automated tests are your defense against such errors. In the simplest case, if the error goes through your tests and into production, then the answer should be:

  • Write a test to reproduce the error.
  • Correct the error.
  • Use the test to verify the fix.

Of course, this applies only to one case, and not every property definition in your code. But if this happens a lot, then you may have a personnel problem, not a technical problem. Someone on the team, well, sleazy. The solution to this problem may not be technical.

+32
Oct 30 '13 at 13:13
source share

Use snippets of code.

For each property supported by the private field, use your own piece of code that you created, instead of writing it from scratch or let IntelliSense do the job (poorly).

In the end, this problem is about conventions and discipline, not language. The nature of C # case sensitivity and the completion of incomplete code in Visual Studio is the reason we make these errors, not the lack of knowledge and design.

It’s best here to eliminate the chance of accidents and have a predetermined way of writing these repetitive things correctly, this is the best way to go. It is also much more automated than memorizing conventions and manually enforcing them.

There is a default code snippet for this in Visual Studio. Type propfull and press "Tab", then specify the name of the instance variable and the name of the property, and it will be convenient for you to go.

+6
Oct 30 '13 at 14:15
source share

In some cases, you cannot get around setters and getters. But maybe you do not need setters and getters if you follow the Tell, Do not Ask principle? Basically, he says that he prefers to have an object for which the data does the work, rather than some other object request from the data object, make decisions, and then write the data back to the data object. See http://martinfowler.com/bliki/TellDontAsk.html

+3
Oct 30 '13 at 19:02
source share

Could you just write a test to cover this?

 int constructorValue = 4; TestClass test = new TestClass(constructorValue); Assert.Equals(test.Test, constructorValue); 

You may not want to write tests right away to cover yourself with future fluctuations, but you have found a mistake, why not protect yourself from it again?

For the record, if I need a private field to store the value for a pulsating getter / setter, I always underline it. There's just something emphasizing that screams privacy!

 public string Test { get { return _test; } set { _test = value; } } private string _test; 
+2
Nov 06 '13 at 9:45
source share



All Articles