Link Round-Up for 9/13/07Comparing String to Integer Conversion Methods in VB.NET

Introduction to the Singleton Pattern in VB.NET

September 13th, 2007

One is the loneliest numberMost VB programmers, even those who’ve haven’t used VB.NET much, know that to create an object they invoke it by calling the class’s constructor using the New keyword. Those who’ve worked with VB.NET may know that there can be multiple constructors for a class and that the .NET Framework automatically builds a no-argument constructor behind the scenes for you at compile time if you don’t supply one. All of these constructors have a Public access modifier so that they can be created from outside the class. Sometimes, there will be cases where you only want one instance of a class in your application. This is where the Singleton Pattern comes into play.

Coding the Singleton Class

There are three steps to creating a simple Singleton class.

First, we will also want to have a module level Private Shared variable that holds the single instance we’re creating:

Public Class MySingleton

    Private Shared _thisInstance As MySingleton

End Class

Next, we want to create a single constructor method with a Protected access modifier, like so:

Public Class MySingleton

    Private Shared _thisInstance As MySingleton

    Protected Sub New()
        'initialization code goes here
    End Sub

End Class

This prevents .NET from creating a default Public constructor and also prevents any caller from creating their own instance of the object. However, by using Protected, the class can still be subclassed if you need to do this.

Lastly, we want to create a Shared accessor method for the class. It would look like this:

Public Class MySingleton

    Private Shared _thisInstance As MySingleton

    Protected Sub New()
        'initialization code goes here
    End Sub

    Public Shared Function GetSingleton() As MySingleton
        '
        ' initialize object if it hasn't already been done
        '
        If _thisInstance Is Nothing Then
            _thisInstance = New MySingleton
        End If
        '
        ' return the initialized instance
        '
        Return _thisInstance
    End Function

End Class

Since this ‘get’ routine is Shared it can be called without having an instance of the object, as seen here.

Dim TestStuff As MySingleton = MySingleton.GetSingleton
Dim MoreStuff As MySingleton = MySingleton.GetSingleton

In this example both TestStuff and MoreStuff are the same object instance, just with different names. That concept seems a bit confusing at first but don’t let that throw you. Just keep in mind that no matter how many variables you use to hold an instance of your Singleton class, it is actually always the same instance.

When Should You Use the Singleton Pattern?

A common place to use this pattern is with forms. You can easily make a form a Singleton class by following the steps above. The only thing you might want to override the OnClosing event to keep the form open but hidden, like so:

Protected Overrides Sub OnClosing(ByVal e As System.ComponentModel.CancelEventArgs)
    e.Cancel = True
    Me.Hide()
End Sub

This technique with forms allows you to insure that only a single instance of a particular form is open at once. This is handy for search forms, certain kinds of pop-ups, and other forms commonly used throughout the application.

Using a Singleton is effective in situations where you need to prevent multiple copies of an object. For example, if you had a device driver for a device that only allowed a single connection at a time, a Singleton would be a good solution.

Another use would be in situations where you wanted to cloak the actual instantiation process or otherwise limit usage of a component. I’ve seen this used for proprietary classes and controls in add-on tools where the programmer wanted to hide initialization details from purchasers or limit trial period users.

There are also some drawbacks to using Singletons as well.

First, they can be a pain for other developers to work with. They’re expecting to use a New call but instead have to use a custom initializer. This can be annoying if there isn’t a good and well documented reason behind it. So, always consider your fellow developers when you implement the Singleton pattern.

Another thing to consider is that you may lose some flexibility in how and when the internal object is created based on how the program runs. This is particularly important in classes and components you provide beyond your own applications. Once again, consider other developers.

Using this pattern can lead to some of the problems associated with global variables. Like Globals, it can make a program harder to debug since state changes can come from anywhere. Because of this, I recommend avoiding putting stateful variables in these classes. Also, simply replacing your global variables with a Singleton class isn’t considered a good design practice. It only gives you the illusion of being object oriented. Avoid using this pattern this way.

I hope this introductory overview has been helpful to you. If you have any thoughts or questions on this topic, please feel free to leave me a comment.

Share This Article: These icons link to social bookmarking sites where readers can share and discover new web pages.
  • Digg
  • del.icio.us
  • Reddit
  • StumbleUpon
  • Technorati
  • DotNetKicks
  • DZone

Entry Filed under: VB.NET Tutorials


Rate This Article:

Not That GoodCould Be BetterOKGoodGreat (6 votes, average: 4.67 out of 5)
Loading ... Loading ...

7 Comments Add your own

  • 1. Joe  |  September 14th, 2007 at 10:19 am

    Would something like this do it?

    Public Class Singleton(Of T As {Class, New})
    	Public Shared ReadOnly Property Instance() As T
    		Get
    			Return SingletonCreator._instance
    		End Get
    	End Property
    
    	Class SingletonCreator
    		Shared Sub New()
    		End Sub
    
    		Friend Shared ReadOnly _instance As New T()
    	End Class
    End Class
    
  • 2. jfrankcarr  |  September 14th, 2007 at 11:40 am

    Thanks Joe. I reformatted your code for readability.

    Yes. That would work for creating a generic Singleton object. The only limitation is that you can only use objects that have a Public New that takes no parameters. String would be an example of an object that would not work although you could wrapper it in another class easily enough if you wanted.

    The interesting thing about this code example is that you can use this Singleton provider to create a Singleton version of a class without having to have the code in the class itself.

    Thanks again for a great example.

  • 3. jamesewelch  |  September 14th, 2007 at 1:19 pm

    Also, the VB.NET Module is implemented as a Singleton, it just doesn’t use lazy instantiation such as this example does. So that makes it just a class with all properties/methods declared as static/shared.


    Public Module MySingleton

    End Module

  • 4. jamesewelch  |  September 14th, 2007 at 1:23 pm

    Oh.. Also, you might want to talk about using a lock to make sure there isn’t two different instantiations of the singleton that happen at the same time.

    example in c#
    http://www.yoda.arachsys.com/csharp/singleton.html

  • 5. jfrankcarr  |  September 14th, 2007 at 1:56 pm

    Thanks James,

    Threading certainly does throw a whole new wrinkle on things. The article you linked to is very informative and helpful.

    To implement the second version, simple thread-safety, mentioned in the linked article, my code example should look like this, if I followed it correctly:

    Public Class MySingleton
    
        Private Shared _thisInstance As MySingleton
        Private Shared PadLock As New Object
    
        Protected Sub New()
            'initialization code goes here
        End Sub
    
        Public Shared Function GetSingleton() As MySingleton
            '
            ' Prevents multiple threads from creating
            ' separate instances
            '
            SyncLock PadLock
                '
                ' initialize object if it hasn't already been done
                '
                If _thisInstance Is Nothing Then
                    _thisInstance = New MySingleton
                End If
                '
                ' return the initialized instance
                '
                Return _thisInstance
            End SyncLock
        End Function
    
    End Class

    James’ code would be the fifth version, fully lazy instantiation, is that correct?

    Thanks again for everyone’s input.

  • 6. Antonio Cavallaro  |  June 19th, 2008 at 12:51 am

    This is my code for full thread-safety:

    ”’
    ”’ Singleton generic thread safe
    ”’
    ”’
    ”’ Codebase by A.Cavallaro
    Public Class Singleton(Of T As {Class, New})
    Private Shared ReadOnly l_ThreadSafeIstance As New T

    ”’
    ”’ Ritorna l’istanza thread-safe del singleton
    ”’
    ”’
    ”’
    Public Shared Function GetInstance() As T
    Return l_ThreadSafeIstance
    End Function

    ”’
    ”’ Nessun costruttore per singleton
    ”’
    ”’
    Private Sub New()
    End Sub
    End Class

  • 7. Antonio Cavallaro  |  June 19th, 2008 at 12:52 am

    Pardon, my personal thread-safe singleton generic object:


    '''
    ''' Singleton generic thread safe
    '''
    '''
    ''' Codebase by A.Cavallaro
    Public Class Singleton(Of T As {Class, New})
    Private Shared ReadOnly l_ThreadSafeIstance As New T

    '''
    ''' Ritorna l'istanza thread-safe del singleton
    '''
    '''
    '''
    Public Shared Function GetInstance() As T
    Return l_ThreadSafeIstance
    End Function

    '''
    ''' Nessun costruttore per singleton
    '''
    '''
    Private Sub New()
    End Sub
    End Class

Leave a Comment

Required

Required, hidden

Some HTML allowed:
<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Trackback this post  |  Subscribe to the comments via RSS Feed


Visit Me At My New Site, Programming In C#

Most Popular Articles

Highest Rated Articles

Categories

Most Recent Articles

Feeds

 Subscribe in a reader

To subscribe by e-mail
Enter your address here

Delivered by FeedBurner

VB Opportunities

Archives