In C#, a field is a variable which is declared directly in a class or struct in C#. A property is a member that provides a flexible mechanism to read, write, or compute the value of a private field.
If you are a beginner, you might get confused between a C# field and a C# property. You can store value using either a field or a property and retrieve the value back. You can even protect both fields and properties using access modifiers such as private or protected. So you might wonder, why we need to have property when you can achieve the same using field or vice-versa?
Object orientated programming principles say that, the internal workings of a class should be hidden from the outside world. If you expose a field you’re in essence exposing the internal implementation of the class.
Therefore we wrap fields with Properties (or methods in Java’s case) to give us the ability to change the implementation without breaking code depending on us.
Properties expose fields. Fields should (almost always) be kept private to a class and accessed via get and set properties. Properties provide a level of abstraction allowing you to change the fields while not affecting the external way they are accessed by the things that use your class.
In this article, we will discuss about C# Fields, Properties and Indexers.
Fields are variables associated with either classes or instances of classes. There are seven modifiers which can be used in their declarations. These include the four access modifiers ‘public’, ‘protected’, ‘internal’ and ‘private’ (discussed in C# Class) and the ‘new’ keyword (discussed in C# Polymorphism). The three remaining modifiers are:
By default, fields are associated with class instances. Use of the ‘static’ keyword, however, associates a field with a class itself, so there will only ever be one such field per class, regardless of the number of the class instances (and the static field will exist even if there are no class instances).
Where a field is readonly, its value can be set only once, either in the class declaration, or in the class constructor (for static fields this will be static constructor). The following code example (which, please note, deliberately doesn’t compile) shows both cases: the field StaticReadonlyInt is set in the class declaration; the field readonlyString is set in the class constructor.
While we’re on declarations, note also that a field declaration can involve multiple fields, as in the following line of code
which is equivalent to
Constants are unchanging types, associated with classes, that are accessible at compile time. Because of this latter fact, constants can only be value types rather than reference types. Constant declarations take the ‘const’ keyword (not ‘static’, even though they are associated with classes), and the five modifiers ‘public’, ‘protected’, ‘internal’, ‘private’ and ‘new’.
If you’ve been reading carefully, you may be struck by the thought: what’s the difference between declaring a field as ‘const’ and declaring a field ‘static readonly’. Good question. The general point is that static readonly fields can be reference types as well as value types. However the main intention is to allows the class designer to remove write privilege of attributes that are intended to be set only during construction, even from methods of the target class (see Private class data pattern).
Properties can be thought of as ‘virtual’ fields. From the outside, a class’ property looks just like a field. But from the inside, the property is generated using the actual class fields.
Property declarations take just those modifiers taken by methods (see C# Method Modifiers) Unlike languages like Java, C# provides dedicated support for accession and mutation of these properties. Suppose, for instance, that a type contains an internal field called ‘age’. With the following code one could specify a property Age, providing accessors and mutators to this internal field.
Notice that the term ‘value’ is used in the above piece of code. This variable always holds the value passed to the ‘set’ block. For instance, the execution of the following line of code (assuming the appropriate class instance) would automatically set ‘value’ in the ‘set’ block to 4.
This property Age can be described as ‘read-write’ since it can be both read from and written to. To make a property ‘write-only’ one simply does not specify a ‘get’ block; to make it ‘read-only’ one does not specify a ‘set’ block. The following piece of code demonstrates the read-only property ‘Adult’:
If properties are ‘virtual fields’, indexers are more like ‘virtual arrays’. They allow a class to emulate an array, where the elements of this array are actually dynamically generated by function calls.
The following piece of code defines a class to hold a list of runners in an athletics race. The runners are held in lane order, and an indexer is exposed which allows the list to be both read from and written to. The indexer deals gracefully with cases in which the lane number passed to it is either too high or too low.
The following simple code illustrates use being made of the class just defined. The name of the person in the race’s first lane is set, and then this name is sent to a console window.
As can be seen from the example, an indexer is defined in a similar way to a property. One important difference is in the indexer’s signature; the word ‘this’ is used in place of a name, and after this word indexing elements are provided.
Indexers aren’t differentiated by name, and a class cannot declare two indexers with the same signature. However, this does not entail that a class is limited to just one indexer. Different indexers can have different types and numbers of indexing elements (these being equivalent to method parameters, except that each indexer must have at least one indexing element, and the ‘ref’ and ‘out’ modifiers cannot be used).
Because indexing elements are not limited to integers, the original description of indexers as ‘virtual arrays’ actually rather undersells them. For example, where the indexing elements include strings, indexers present themselves more like hash tables.
The following code shows an implementation for the RaceDetails class of an indexer whose indexing element is a string. Using this indexer it is possible to refer to a lane using the name of the person currently filling that lane.
The following piece of code gives an example of the kind of use one might make of this string indexer.
Subscribe to Code with Shadman
Get the latest posts delivered right to your inbox