Home > OS >  What's the sense of this difficult getter and setter construction in a Settings class?
What's the sense of this difficult getter and setter construction in a Settings class?

Time:09-17

I'm working with a sealed Singleton Settings class, where I've found following definition of a property:

public Boolean aRandomProperty
{
  get
  {
    return (Boolean)this["aRandomProperty"];
  }
  set
  {
    this["aRandomProperty"] = value;
  }
}

While having a look at the source code, I've seen that this property is used as:

SomeOtherVariable = Settings.Instance.aRandomProperty;
Settings.Instance.aRandomProperty = true;

I believe that a simple definition of the property, like the following, would work too:

public Boolean aRandomProperty;

Can anybody explain me what more can be done with that difficult getter/setter definition (I also completely don't understand the this["aRandomProperty"] part)?

For your information: the Settings class is derived from System.Configuration.ApplicationSettingsBase.
Nowhere in the code, there is this[ (even not with a bunch of spaces), so I believe there's no indexer defined.

CodePudding user response:

Using get and set, you define a property whereas with your proposed code (public Boolean aRandomProperty;) a simple field is declared. As @VinayC also explains, properties look like fields from the outside, but are defined as code. This way, a property hides the details of the class and enable you to

  • Allow easy access from the outside while at the same time
  • Give you the flexibility to store the data internally as it fits your needs

Especially the latter is important when we look at your specific example:

public Boolean aRandomProperty
{
  get
  {
    return (Boolean)this["aRandomProperty"];
  }
  set
  {
    this["aRandomProperty"] = value;
  }
}

This property uses the indexer of the base class to store the data. In your case, the base class ApplicationSettingsBase is used to access the configuration of the application. This class offers a so called indexer, a specific kind of property that is defined like this:

public object this[string key]
{
  get 
  {
    // Retrieve data using the key
  }
  set 
  {
    // Store data using the key
  }
}

This kind of property allows your class (or in this case the base class) to be used like:

var myInstance = new MyClassWithAnIndexer();
myInstance["test"] = 123;
var value = myInstance["test"];

This is often used to store arbitrary data in your class without knowing their name/key beforehand. Configuration settings are a good example for this as they usually are put together from key-value-pairs where key can be anything.

Wrapping up, the aRandomProperty in your sample is a property that uses the indexer of the base class to store and retrieve the value. Possible reasons for this are

  • A caller of the class does not need to know the name of the key "aRandomProperty". It is much more convenient to access the property
  • Also, the caller cannot mis-type the key; using the property, the compiler raises an error if the property name is wrong.
  • The specific key that is used can be changed later in a single spot because a caller of the class only knows the public interface of the class in the form of the property.

The documentation provides details on properties and indexers.

CodePudding user response:

The syntax that you are proposing is a called field in C# as opposed to the property (getter/setter syntax). There also exists a shortcut syntax for property such as

public Boolean aRandomAttribute { get; set; }

A lot more syntax options are available in documentation.

The main reason for using property instead of field for defining attribute is the flexibility that you get. For example, you can have some behavior in getter/setter to have some side effect, or to compute dependent value or to do some validation or to notify interested parties etc. Read-only attributes is something that is possible with property syntax (by using non-public setter).

Perhaps, next question can be why not define field at first and then change to property when need arises to inject behavior (as is the current code that you have sighted). However, this is a breaking change at binary level (library consumption); so defining it as a property makes it future proof. With Complier/JIT optimization, there is almost no performance penalty (accessing field as opposed to making getter/setter method call) since property calls will get translated to direct calls to backing field.

  • Related