XTab's Blog

Ged Mead's Blog at vbCity

This blog hosted by:
http://blogs.vbcity.com      
  Home :: Syndication  :: Login

OctNovember 2008Dec
SMTWTFS
2627282930311
2345678
9101112131415
16171819202122
23242526272829
30123456

Archives

Topics

Ramblings

VB.NET

  There's something that's always bothered me a little bit about creating classes. We go to the trouble of creating backing Private fields and Public properties in order to implement data hiding - right?   And when we want to include data validation, we usually use properties for that task, don't we?

   But then what do we do? We go and create a parameterized constructor that lets client code push invalid data straight into a field. At least that's what I see in most of the class building examples I've come across - both in books as well as in real world code. It's quite rare to see values passed into properties in a parameterized constructor; fields seem to be the most popular recipients of initialization data.

  I'm surprised at how many times I've seen this done. Of course it's possible to include validation in the constructor too (but the examples I've seen that use fields rarely seem to do this; leaving the door to bad data wide open)

  Luckily, we now have a very easy solution - Object Initializers.

  In fact, you could claim that with the arrival of Object Initializers the parameterized constructor has just about become redundant.

  Parameterized constructors were devised to make it easy to pass arguments in to a constructor and to avoid having to add several lines of code for property values when initializing a new object. You know the sort of thing:-

Code Copy
Dim sr As New SalesRecord
      sr.CustomerName = "Joe Soap"
      sr.Total = 2399.65
       '  etc  etc

  which was short-circuited with :-

Code Copy
Dim sr As New SalesRecord("Joe Soap", 2399.65)

  However, as I said, in most cases people code this so that it assigns the CustomerName and Total values directly to the fields.

  Object Initializers step round this issue while still enabling client code to be fairly concise. How it works is that when you initialize an instance of a class object you are allowed to use the 'With' keyword as a way of assigning values to properties, all in one line of code.

  Let's knock up a quick class to demo this.

Code Copy
Public Class Product

    Private _itemcode As String
    Public Property ItemCode() As String
        Get
            Return _itemcode
        End Get
        Set(ByVal value As String)
            _itemcode = value
        End Set
    End Property


    Private _cost As Decimal
    Public Property Cost() As Decimal
        Get
            Return _cost
        End Get
        Set(ByVal value As Decimal)
            If value > 0 Then
                _cost = value
            Else
                _cost = 0
            End If
        End Set
    End Property


    Private _itemname As String
    Public Property ItemName() As String
        Get
            Return _itemname
        End Get
        Set(ByVal value As String)
            _itemname = value
        End Set
    End Property


End
Class

  So, three fields, three properties (one of which includes some validation) and just the default constructor. To create a new instance of the Product class and assign values to any of the properties that interest us, this is what we can now do:

Code Copy
Dim P1 As New Product With {.ItemName = "Widget", .Cost = 0.99}

  That's it!    A Product instance with those values for the ItemName and Cost properties now exists. And of course the validation is applied effectively at the time of instantiation to avoid any unacceptable values being passed.

  Note that the property assignments are contained inside curly braces and not standard parentheses.

  There are several advantages to this approach. Not only does it get around the validation problem I mentioned at the start, but it also allows you to pick'n'mix the properties you want to assign values to when you instantiate the object. As you saw in my example above, I chose only to assign values to two of the properties.

   And if that's not enough to get you interested, there's more. You even have the further advantage that you can pass the values in any order you like (unlike the standard parameter arguments which have to be passed in a strict order).

   Finally, if there is a parameterized constructor available that contains some, but not all, the arguments you want to pass in, then you can simply combine the two approaches and use the constructor's parameters, as well as the object initializers, all in one chunk of initialization code.

  So if you had this parameterized constructor in the class:-

Code Copy
  Sub New(ByVal code As String)
        Me.ItemCode = code
  End Sub

  you could use the following code to assign values to all three properties:-

Code Copy
Dim P2 As New Product("TOOL12") With {.ItemName = "Spade", _
    .Cost = "12.99"}

   How cool is that?

   To be honest, I'm not sure how often I'd want to do that - given that I can do the same thing using three object initializers - but it's an option to consider.

  So there it is. A new feature that you may have heard about but weren't sure if it was going to be of use to you. Personally, I think it's great and plan on implementing this approach whenever I can from now on.

posted on Thursday, August 28, 2008 7:09 AM

Feedback

No comments posted yet.

Post Feedback

Title:
Name:
Url:
Comments: 
Protected by Clearscreen.SharpHIPEnter the code you see: