One of things I really like about working with C# is using properties. They are incredibly flexible and house the data used by our applications. I have noticed that as C# matured over the last 12+ years, additional functionality has been added to them making them a “must have” feature in almost all classes. I have attempted to identify most of the ways we use C# properties today and am going to list them here. Hopefully, I discovered them all. Here they are!

The Basics of C# Properties

In VB and C#, we use properties to encapsulate a class field or calculation. They typically contain accessor and mutator methods (getters and setters) for class fields. The fields are class-level variables representing the state of an object. Properties allow us to inject business logic and data preparation logic inside of the “get” and “set” blocks of a property. Properties also allow us to code against them like fields, even though they really are made up of one or two methods.

As a best practice for enforcing encapsulation, all code outside of a class that contains properties should always refer to the properties instead of referring to the class fields directly. This best practice should also apply to other class members in the same class or derived class. Here is a simple example.

public class Car
{
  private string _Make;
  public string Make
  {
    get { return _Make; }
    set { _Make = value; }
  }

  private string _Model;
  public string Model
  {
    get { return _Model; }
    set { _Model = value; }
  }

  public string FullName
  {
    get { return Make + " " + Model; }
  }
}

You can see the two private fields (_Make and _Model) are encapsulated with their own public properties. A third property was created (FullName) that uses the other two properties. As well, because it only has a “get” block, it is considered “read only”. As a best practice and for clarity, if you feel you need to define a “write only” property, it is probably best to just to define it as a regular method instead. The keyword “value” is used to assign a value to the private field that the property is encapsulating. Here is the code that uses it.

class Program
{
  private static void Main()
  {
    Car firstCar = new Car();
    firstCar.Make = "Mercury";
    firstCar.Model = "Cougar";
    Console.WriteLine("My first car was a {0}.", firstCar.FullName);
  }
}

Even though .NET properties are defined as single class members, the Intermediate language (IL) code will show the truth, which is that each part (get/set) of the property is really defines as a “getter” method and “setter” method. However, you only have to program against the properties directly and do not even have access to these methods!

2014-05-06_16-24-21

Visual Studio Support

Visual Studio offers a couple of cool features for helping you with properties. Adhering to Martin Fowler’s standards on refactoring (http://www.refactoring.com), Visual Studio can help you encapsulate fields via a simple context menu. Simply right-click a class field and click Refactor | Encapsulate Field… This option will generate the associated property, saving you typing.

2014-05-06_16-01-45

As well, Visual Studio has a nice set of snippets to help you define properties. Just start typing “pro”, select the appropriate snippet, and click the <Tab> key twice to generate the property. Experiment with the snippets to see which one you like!

2014-05-06_16-05-53

Indexers

C# Indexers look and feel like properties because they are! They typically encapsulate an array or collection within a class. They look a little strange because they are named “this”.

public class Car
{
  private List<Passenger> riders = new List<Passenger>();
  // Indexer encapsulating the riders collection.
  public Passenger this[int index]
  {
    get { return riders[index]; }
    set { riders.Insert(index, value); }
  }
}

Using the indexer couldn’t be simpler:

private static void Main()
{
  Car firstCar = new Car();

  Passenger brother = new Passenger();
  brother.FirstName = "Bryan";
  brother.LastName = "Mickelson";
  firstCar[0] = brother;

  Passenger uncle = new Passenger();
  uncle.FirstName = "Jim";
  uncle.LastName = "Samuelson";
  firstCar[1] = uncle;

  Console.WriteLine("Passenger 0: {0} {1}", 
    firstCar[0].FirstName, firstCar[0].LastName);
  Console.WriteLine("Passenger 1: {0} {1}", 
    firstCar[1].FirstName, firstCar[1].LastName); 
}

Object Initialization Syntax

The code in the last example was really “wordy” since we were using hard-coded values. It would have been a lot shorter if we’d have constructed the objects inline and initialized their properties when we called the Passenger constructors. This is object initialization syntax. The initialization code could have been written with three lines of code instead of nine, like this:

static void Main()
{
  Car firstCar = new Car();
  firstCar[0] = new Passenger() { FirstName = "Bryan", 
    LastName = "Mickelson" };
  firstCar[1] = new Passenger() { FirstName = "Jim", 
    LastName = "Samuelson" };
  Console.WriteLine("Passenger 0: {0} {1}", 
    firstCar[0].FirstName, firstCar[0].LastName);
  Console.WriteLine("Passenger 1: {0} {1}", 
    firstCar[1].FirstName, firstCar[1].LastName);
}

Technically, this is how C# attributes have support inline initialization since .NET 1.0. When using a .NET attribute, you can either pass in comma-delimited arguments into its constructor or assign properties as name/value pairs. Before object initialization syntax was added in .NET 3.5, I actually saw developers abusing attributes just for this cool capability!

Here are a couple of examples. The DataContract attribute has a couple of public properties being set in its declaration. The Obsolete attribute is passing two arguments to the ObsoleteAttribute constructor.

// Set the Name and Namespace properties to new values.
[DataContract(Name = "Customer", Namespace = "https://www.intertech.com")]
public class Customer { }
  
[Obsolete("HorseAndBuggy is obsolete. Use Car instead.”, true)]
public class HorseAndBuggy { }

Refined Property Declaration

Starting with .NET 2.0, you can now tighten the security (visibility) of just the get/set part of a property. Many times we want the “get” section to be available at the level of the property (typically internal or public) but we’d also like the “set” block to be private or protected. Note that you can only set the visibility of one of the parts (not both) and it must be a tighter level of security, not looser.

public int CurrentSpeed
{
  get { return _CurrentSpeed; }
  protected set { _CurrentSpeed = value; }
}

Auto-Implemented (Automatic) Properties

Defining a private member and then a full-bodied property takes up a lot of whitespace. This is especially wasteful if there is no custom business logic being added to the properties. Automatic properties allow you to define a private field and property in one single line of code.

public int CurrentSpeed { get; set; }

Note that you cannot define a “read only” or “write only” property with this markup. As well, the compiler will actually generate a private field for this property but you won’t have access to it. In the example below, it shows the private field was defined as k__BackingField.

2014-05-06_17-39-18

Note that you can tighten security to the get/set part, like this:

public int CurrentSpeed { get; protected set; }

If you ever need to add business logic to an automatic property, then you will need to convert it back into a full property declaration. Thankfully, even if you have several classes or even assemblies compiled against an existing class with automatic properties, the code should still work even after you flesh out the property. You haven’t broken the class’ interface. You will have to add a private field but that still won’t affect the public/internal interface.

Anonymous Objects

You can also create anonymous objects with public properties, although their values will be “read only”. You also get these objects returned to you from LINQ queries. You can only declare these within a method and you must use the var keyword. As well, all the standard Object class members have already been overridden for you to be more useful. Here is a simple example:

public void Drive()
{
  var Engine = new { Displacement = "6.1L", 
                     HorsePower = "425 HP", Torque = "420 lbs." };
  // Outputs “{ Displacement = 6.1L, HorsePower = 425 HP, 
  //            Torque = 420 lbs. }”
  Console.WriteLine(Engine);
}

Property Inheritance

You can define properties as abstract, virtual, or override in a class. Yes – these types of properties can be overridden in a derived class. You can choose to override just the get/set part of the property or both parts. In the example below, the Car class has a virtual property and the set part off the property is overridden in the SportsCar class to convert the letters to be completely uppercased.

public class Car
{
  private string _carColor = string.Empty;
  public virtual string Color
  {
    get { return _carColor; }
    set { _carColor = value; }
  }
}

class SportsCar : Car
{
  public override string Color
  {
    set { base.Color = value.ToUpper(); }
  }
}

class Program
{
  static void Main()
  {
    Car firstCar = new Car();
    SportsCar sc = new SportsCar() { Color = "Red" };

    // Writes out “Color: RED”
    Console.WriteLine("Color: {0}", sc.Color);
  }
}

Interface Implementation

Finally, I wanted to mention that besides methods and events, you can also define properties and indexers as part of an interface. Any class that implements the interface must include these members. Below, the CurrentSpeed property has been defined and the Passenger indexer is also required by this interface.

public interface IVehicle
{
  int CurrentSpeed {  get; set; }
  Passenger this [int index] { get; set; }
}

I hope you found this little exploration into C# properties helpful, if not at least a brief primer to remind everyone how properties can be used. Best wishes to all.