5

I have seen some code and thought that something seems wrong with it, so I would like to know if it is acceptable for good coding or not, my first thought is no.

Consider:

class MyClass
{
    private string m_MySuperString;
    public string MySuperString
    {
        get { return m_MySuperString; }
        set { m_MySuperString = value; }
    }

    public void MyMethod()
    {
        if (blah != yada)
        {
             m_MySuperString = badabing;
        }
    }

    public void MyOtherMethod()
    {
        if (blah == yada)
        {
            m_MySuperString = badaboom;
        }
    }
}

Is this kind of direct access to the Backing Field an acceptable practice or is it bad coding - or should I ask what is the point of the Property Accessor, and if this is done internally in a class with public members , access is allowed by multiple components - is it possible to have a crash - I would venture in a multi threaded application a crash should be expected.

Please any thoughts ? I have looked at this Link on SO and others> Why use private members then use public properties to set them?

EDIT

Let me be clear since there is good info being provided and rather respond to all answers and comments directly. I am not asking about what properties are for, not if I can do auto implemented properties, private setters, OnValueChange notifications, logic on the properties. My question is in regards to accessing that backing field directly - for example if you have say a mutlithreaded scenario - isn't the whole point of the synclock on the getters/setters - to control access to the backingfield ? Will this kind of code be acceptable in that scenario - just adding a syncLock to the getter and setter ?? Keep in mind the code in the constructor of myClass is an example - the code can be in any additional method - such as the updated class - Method1

END EDIT

Community
  • 1
  • 1
Ken
  • 2,518
  • 2
  • 27
  • 35
  • This is really subjective. I recommend checking out Chapter 8, Section 1 of @JonSkeet's C# In Depth for more information on automatically implemented properties. In short answer to your question, no, there's nothing wrong with this code. – Chaim Eliyah Jun 20 '16 at 20:58
  • You can do whatever you feel you need to within the class. The property is for your interface to other types. You can read up on the OO principle of encapsulation if it helps. – itsme86 Jun 20 '16 at 20:59
  • @Chaim Eliyah ok so nothing wrong with the code ; is there any issue regarding this and multi-threaded access from outside the class - if the the backing field be internally set (from perhaps even two methods in the class) and access to the property / methods can be done externally how does one control access to the backing field except all access goes through the property ? I am thinking multiple threads running on this class will cause an issue - or am I completely wrong ? I thought that was the whole point of placing a synclock on the property accessors ? – Ken Jun 21 '16 at 17:09
  • What you could expect is that in a multithreaded application the value of `blah` or `yada` might change prior to the execution of the code, so you might get unpredictable behavior. You could use [locks](http://stackoverflow.com/questions/7161413/thread-safe-properties-in-c-sharp) or you could use a [thread-safe container](http://stackoverflow.com/a/30492073/2496266) or you could just decide that you don't care because these are, after all, in-memory properties in a managed-runtime language and just trust that the execution will happen in the predicted order. It really depends on your design. – Chaim Eliyah Jun 21 '16 at 19:09
  • @Chaim Eliyah , Ok if you will post your comments as answer - I will accept that. Thanks for the links as well - I will do more reading in my spare time. – Ken Jun 21 '16 at 19:14
  • Sure, no problem! Done and done. – Chaim Eliyah Jun 21 '16 at 23:47

3 Answers3

2

Properties in Object Oriented Programming (OOP) help to enforce Encapsulation. The idea is that only the object itself is allowed to interact with its own data (i.e. fields). Access to the object's data from outside is only allowed through methods. In Java, for instance, you have to explicitly write get- and set-methods. Properties in C# have a special syntax that combines both of these methods in one construct, but the getters and setters are in fact methods.

This also means that an object is absolutely allowed to access its own fields directly.

There are cases, however, where property getters and setters perform additional logic. A setter might raise the PropertyChanged event or do some validation. A getter might combine several fields or yield a formatted or calculated value. If you need this additional logic to be performed, then you must access the properties instead of the fields. If a property is auto-implemented, then you have no choice (in C#), since the backing field is hidden and not accessible. (In VB it is hidden from IntelliSense but accessible from within the class.)

Olivier Jacot-Descombes
  • 104,806
  • 13
  • 138
  • 188
  • "This also means that an object is absolutely allowed to access its own fields directly." Just because I can does it mean I should? The additional logic is more to my point for example a synclock in a multithreaded application, isn't the point of the synclock on the property accessor to control access to the backing field ? Would the threads crash when internal access is directly on the backing field like and I have an external component requesting access. – Ken Jun 21 '16 at 17:23
  • The encapsulation principle does not require an object to access its own data through method calls. Therefore I don't think it is a bad practice to do it. But of course if the logic requires it, that's another thing. Synclock logic is not any different in this respect. – Olivier Jacot-Descombes Jun 21 '16 at 19:31
1

In the use case described , You can define this as follows using auto-implemented properties

public string MySuperString{ get;  set ;}

you should use a backing filed if you need to do some input verification or the property is different than the internal fields for example

public string FullName{ get { return firstName + LastName} }

another benefit of using properties is you can define them in an interface , which is better in the long run for future features to be added

Shachaf.Gortler
  • 5,655
  • 14
  • 43
  • 71
  • Note additionally that you can have different access modifiers for `get` and `set` if your requirements so dictate, e.g. you could do `public string MyProp { get; private set; }` – Eric J. Jun 20 '16 at 21:04
  • Although the question is pretty subjective, I upvoted this answer because the backing field is an implementation detail that can be abstracted away in this case. Higher abstraction = less chance of inadvertent error. – Eric J. Jun 20 '16 at 21:05
1

I recommend checking out Chapter 8, Section 1 of @JonSkeet's C# In Depth (from which I've shamelessly taken the below snippets for the purpose of education) for more information on automatically implemented properties. In short answer to your question, no, there's nothing wrong with this code.

Consider that the following snippet:

public string Name { get; set; }

is compiled as

private string <Name>k__BackingField;
public string Name
{
     get { return <Name>k__BackingField; }
     set { <Name>k__BackingField = value; }
}

...so the compiler is already doing the work for you that you've done above. There are ways to modify what it's doing, but those don't really answer the question. One example given in the book for thread safety is this:

//code above, plus
private static int InstanceCounter { get; set; }
private static readonly object counterLock = new object();

public InstanceCountingPerson(string name, int age) {
    Name = name;
    Age = age;
    lock (counterLock) // safe property access
    {
        InstanceCounter++;
        // and whatever else you have to do with the lock enabled
    }
}

--Which is a pattern also referenced in this SO question. However, as pointed out there, locks are (a) potentially slow, (b) might not actually ensure their job is done because they have to be released at some point, and (c) rely on the trust system, because they sort of naively assume that anything wanting to access that object will make proper use of the lock (not always true, at least not in some of the code I've seen :D ). The advantage of the getter and setter methods is that you can enforce the pattern of using the lock (read: properly encapsulate the field, as others have suggested) for any instance of your class.

Another pattern you might consider, however, is Inversion of Control. With a Dependency Injection container, you can specify the level of thread safety you are comfortable with. If you are comfortable with everyone waiting for a singleton instance of your object, you can declare that all references to the object's interface reference the same object (and must wait for the object to become available), or you can determine that a thread-safe instance of the object should be created each time it is requested. See this SO answer for more details.

Note:

Any peer-reviewed criticism of the above ideas will be graciously accepted and added to the answer, as I'm sort of a thread safety dilettante at this point.

Community
  • 1
  • 1
Chaim Eliyah
  • 2,743
  • 4
  • 24
  • 37