Back to Basics: The Perfect .NET Bean Property
A few weeks back I wrote about writing more rigorous bean properties in Java. At present I'm on a .NET gig, and over time I've found myself moving more and more away from using Microsoft .NET's Property construct and towards writing Java-style bean properties in my VB.NET and C#.NET classes. One of my colleagues actually guessed that I'm a Java programmer because of the way I've been writing classes. I believe there's some significant benefits to using the Java bean property approach in .NET classes, and I'd like to share some of those benefits with you now. First though I'll try to place where exactly .NET properties fit in.
Note: The most of the example code in this document is all VisualBasic.NET. I provide a C# version of the full "Perfect .NET Bean Property" at the end.
Why You Shouldn't Use .NET Properties
What the Heck is a .NET Property Anyway?
Microsoft .NET has the (as far as I know) unique Property syntactical construct. In object-oriented terms, a property is an element of an object's state. The problem is that the semantic difference between Properties and other more typical programming constructs are blurry if there is any significant difference at all.
For example, let's say we had to create a Person class with a FirstName property. Typically the getter would be implemented like this:
Private m_firstName As String = Nothing
Public Property FirstName() As String
Get
Return m_firstName
End Get
...
End Property
The same thing could be expressed with a function like this:
Private m_firstName As String = Nothing
Public Function FirstName() As String
Return m_firstName
End Function
Aside from the Property option requiring more code, the only other practical difference is the icon that you see in the Object Browser window and the IntelliSense prompt.
- Property:

- Function:

So the Get part of a .NET property is really.. a Function. Likewise, a .NET property setter is a Sub. For example:
Private m_firstName As String
Public Property FirstName() As String
...
Set(Value As String)
m_firstName = Value
End Set
End Property
is equivalent to
Private m_firstName As String
Public Sub FirstName(Value As String)
m_firstName = Value
End Sub
Well, almost anyway. There is a difference here in that you use the assignment operator to put a value into a property via it's setter, whereas a sub takes the value as a parameter.
So what is a property? It's syntactic sugar that let's you use assigment operator when setting values into an object's state. This is nice because it allows us to create easier to read API's. The problem with .NET properties comes from one small oversight in the Common Language Runtime spec, which is...
No Mixed Protection Modifiers
In .NET you can't use different protection modifiers on the Get and the Set parts of a property. For example you can't make the Get part Public and the Set part Private. Perhaps the language designers thought the readonly and writeonly modifiers provided equivalent to having mixed protection modifiers, but again you can't have scope the readonly/writeonly by protection modifier.
So what's the big deal? Instead of a public getter and private setter, you can just make your properties readonly, and when you want to set the property from other code internal to the class, just set the field directly.
Public Sub New( _
firstName As String)
m_firstName = firstName
End Sub
Private m_firstName As String
Public ReadOnly Property FirstName() As String
Get
return m_firstName
End Get
End Property
The problem with this approach is that you're not controlling or validating the values that are allowed to be set into the property. A private Setter would make the ideal central point to write a bit of what I refer to as "inbound validation" code to make sure that unacceptable values are rejected.
You could argue that this inbound validation isn't that important anyway since it's our code and we will be testing it before we ship anyway, but inbound validation like this provides an important defensive coding mechanism against us making mistakes, and actually saves diagnosis time when we do. See Inbound / Outbound Validation below for more on this.
Microsoft Is As Confused As Me
Microsoft's own programmers seem to be as unsure about the purpose of .NET properties as I am. Even in the System.* namespaces there seems to be some conflict about when one should use a Property, and when one should use a Sub or a Function. For example:
- To set the "stdin" reader, you use the sub System.Console.SetIn(System.IO.TextReader), but to retrieve it you use the readonly property System.Console.In.
- System.Object has a GetHashCode function to get the object's hash, while the System.Security.Cryptography.HashAlgorithm provides a Hash property.
- Most collections provide access to the items they contain via an Item property which takes some parameter to indicate the particular item to be retrieved whereas System.Xml.XmlNodeList and System.Xml.XmlNamedNodeMap both have Item methods.
No More Properties
Okay, so for the moment we won't use .NET Properties. We'll come back to them later and try to figure out where they are and are not appropriate.
For the moment, where we want to implement a readable property, we'll use a Function, and where we want to implement a writeable property, we'll use a Sub. Also, we'll use the JavaBean style "get" and "set" prefixes, but for the VB.NET examples we'll follow the normal convention and capitalize those to "Get" and "Set". For example, instead of:
Private m_firstName As String = Nothing
Public Property FirstName As String
Get
Return m_firstName
End Get
Set(Value As String)
m_firstName = Value
End Set
End Property
We will implement a Java-style Bean Property getter / setter pair like this:
Private m_firstName As String = Nothing
Public Function GetFirstName() As String
Return m_firstName
End Function
Public Sub SetFirstName(Value As String)
m_firstName = Value
End Sub
From here on, we'll refer to this type of implementation as a .NET Bean Property.
Inbound / Outbound Validation
The typical Property written by a .NET programmer goes something like this:
Private m_firstName As String
Public Property FirstName As String
Get
Return m_firstName
End Get
Set(Value As String)
m_firstName = Value
End Set
End Property
This is, well, useless. Quite frankly, we might as well have abbreviated our code to:
Public FirstName As String
Semantically identical, and less typing to boot. I mean, why bother writing a property when all you're going to do is provide direct unfettered access to the underlying field anyway? The only difference in between the two pieces of code above is the icon that appears in Object Browser and IntelliSense.
- Property:

- Function:

The key thing that this code is missing is validation on the value both as we Get it and as we Set it.
It's easy to do add constraints on our .NET Bean Property. All we need to do is put in the appropriate checks, and if any of those checks fail, throw the right type of Exception. For example, if our FirstName property is mandatory (cannot be Nothing or empty string), we could add those constraints like this:
Private m_firstName As String = Nothing
Public Function GetFirstName() As String
If m_firstName Is Nothing Or _
m_firstName = "" Then
Throw New Exception("firstName not set")
End If
Return m_firstName
End Function
Public Sub SetFirstName(Value As String)
If Value Is Nothing Or _
Value = "" Then
Throw New ArgumentException( _
"firstName cannot be empty")
End If
m_firstName = Value
End Sub
The three key things we've done in this code which differentiate it from the typical property implementation are:
- Added outbound validation to the getter. If the property is "empty" then this validation will throw an exception.
- Added inbound validation to the setter. If any attempt is made to set the field to an empty value, we will throw an ArgumentException.
- Explicitly initialized the property to an empty state. This is important because if we create a new instance and the immediately access the Getter, the Getter's outbound validation will kick in and throw an Exception. In other words it's impossible for us to use that property without having explicitly set a value into it at some point.
Read-Only and Write-Only Properties
To make a .NET Bean Property read-only or write-only is just a matter of changing the protection modifiers on the getter and setter. Our FirstName property can be made read-only just by making the setter private:
Private m_firstName As String = Nothing
Public Function GetFirstName() As String
If m_firstName Is Nothing Or _
m_firstName = "" Then
Throw New Exception("firstName not set")
End If
Return m_firstName
End Function
Private Sub SetFirstName(Value As String)
If Value Is Nothing Or _
Value = "" Then
Throw New ArgumentException( _
"firstName cannot be empty")
End If
m_firstName = Value
End Sub
Note that we still retain the setter, and we still use it for all the internal code that want's to set this property. This is important because it means our inbound validation is still being applied to every value that goes into the property.
A write-only property is achieved by making the getter private or protected, and making the setter public.
Optional Properties
Introduction
Sometimes properties are optional. You may or may not provide a value for the property. Let's say we had a middle-name property on our Person class which is optional (not everyone has a middle name). It turns out we still need the same inbound and outbound validation as for the FirstName property. After all, it's not valid to set a person's middle name to Nothing or "". So our basic MiddleName .NET Bean Property follows the same format as the FirstName property.
Private m_middleName As String = Nothing
Public Function GetMiddleName() As String
If m_middleName Is Nothing Or _
m_middleName = "" Then
Throw New Exception("middleName not set")
End If
Return m_middleName
End Function
Private Sub SetMiddleName(Value As String)
If Value Is Nothing Or _
Value = "" Then
Throw New ArgumentException( _
"middleName cannot be empty")
End If
m_middleName = Value
End Sub
Querying State
When consuming optional properties we need to be able to check whether or not the property has a value.
Our outbound validation on our getter means that we can't do something like this:
If Not person.GetMiddleName() Is Nothing Then
...
End If
If the MiddleName property is Nothing, then the outbound validation in GetFirstName will kick in and throw an exception. The problem is that Nothing is not really a value for the property, it's a flag indicating the property's state. So what we need is a special function to check the properties state:
Public Function HasMiddleName() As Boolean
Return Not m_middleName Is Nothing
End Function
So the check to see if we have a value for the optional MiddleName property becomes:
If person.HasMiddleName() Then
...
End If
Clearing the Property
We may want to be able to reset the value of an optional property back to it's empty state. Here we face a similar problem to the one we had when trying to check if an optional property was set - in the following code, our in-bound validation will kick in and reject the valid value.
person.SetMiddleName(Nothing)
Again, Nothing represents the empty state, not a value. So we need a dedicated method to set the field to that state:
Public Sub ClearMiddleName()
m_middleName = Nothing
End Public
Mandatory Properties
Introduction
A mandatory property is one that must have a value for the object to be valid.
Since it's not valid for a mandatory property to be empty, there's no need to provide Has and Clear methods we just discussed for optional properties.
Mandatory Properties Belong In Constructors
Since a mandatory property must have a value for the object to be valid, these properties should be supplied through the constructor of your object.
For example, if FirstName and LastName were mandatory properties of our Person class, we would write a constructor that accepts those values as parameters, and we would not provide a no-arg constructor.
Public Sub New( _
ByVal firstName As String, _
ByVal lastName As String)
Me.SetFirstName(firstName)
Me.SetLastName(lastName)
End Sub
Note that even in the constructor we use the setters to set the underlying field values because we always want the inbound validation to run.
Mandatory Properties With Default Values
Where a mandatory property can take a default value if none is specified during construction, that default value should be set in the constructor as well.
For example, if we had a mandatory CountryOfBirth property, but we wanted to make it default to "Thailand" when it was not specified, then we might do something like this:
Private Shared ReadOnly String DEFAULT_COUNTRY_OF_BIRTH = "Thailand"
Public Sub New( _
ByVal firstName As String, _
ByVal lastName As String, _
ByVal countryOfBirth As String)
Me.SetFirstName(firstName)
Me.SetLastName(lastName)
Me.SetCountryOfBirth(countryOfBirth)
End Sub
Public Sub New( _
ByVal firstName As String, _
ByVal lastName As String)
Me.SetFirstName(firstName)
Me.SetLastName(lastName)
Me.SetCountryOfBirth(DEFAULT_COUNTRY_OF_BIRTH)
End Sub
.NET Bean Properties vs Normal Properties
Where to use Normal .NET Properties
So if the Property construct can be replaced by a JavaBean style approach, and if there are benefits (mixing of protection modifiers, finer control, less code) to doing so, then what is the Property construct good for? Well, here's the rules that I'm following at the moment:
- Classes used purely for representing data, sometimes referred to as model objects or in Java-speak POJO's, get Bean Properties, and DON'T get .NET Properties.
- Form and UserControl classes get mandatory bean properties with default values, which are typically private and are exposed as .NET Properties (see Exposing A Property, below).
- Exception classes get mandatory bean properties which are always private and are exposed as ReadOnly .NET properties. You could just offer access to the data within an Exception class via the bean property getter, but as Exceptions are likely to be consumed by other software, I make a concession to convention here by providing the .NET property.
Exposing A Property
Even where I use a normal property, I still write a .NET Bean Property to drive it, and just expose that bean property through a normal Property construct. For instance to add a FirstName property, I'd just wrap my FirstName .NET Bean Property like this:
Public Property FirstName() As String
Get
Return Me.GetFirstName()
End Get
Set(Value As String)
Return Me.SetFirstName(Value As String)
End Set
End Property
Note that the reason I chose earlier to use the Java naming standard of prefixing the bean property getters and setters with Get and Set was so that when the bean property is wrapped with a regular property, there's no naming ambiguity.
Full Examples
I've written a simple Person class that demonstrates the principles described above of:
- Inbound / outbound validation
- Optional properties
- Mandatory properties
- Mandatory properties with default values
Visual Basic.NET and C# versions are here:


