Posts filed under 'VB.NET Tutorials'

Introduction to the Generic List - Part I

A Generic List is a lot better than a generic beer!Earlier I had gone over some other aspects of the System.Collections.Generic namespace, such as the Queues, Stacks, and Action and Predicate Delegates. I received a couple of emails asking me to also go over the plain old List object as well and include any helpful tricks I might have for them. So, this will be the topic for this two part series of articles.

The Basics

The generic List is a type-safe version of the .NET ArrayList. It can dynamically change its size as items are added or removed. It can also be searched, sorted and enumerated. Since the List is type-safe, meaning you have to specify the type of items going into it, it will generally perform better than ArrayList. All in all, the generic List is a better way to store data in memory in most cases than the older ArrayList and plain old array models.

Adding and Removing Items

While The Add, Remove, and Clear methods are obvious, there are some additional related methods that you might find useful.

We’ll look at AddRange first. As you can guess, it loads more than one item at once to the List. It might be a bit daunting for you when you look at the parameter required for this method.

collection As System.Collections.Generic.IEnumerable(Of T)

What does that mean? What it is looking for here is a collection that implements the IEnumerable interface and has the right type. This includes standard arrays and many other collection types just as with several other objects that implement this method in the .NET Framework. Let’s look at a few examples.

In this example, we’re going to take a comma delimited string entered in a TextBox and place it in our List:

Dim EmailAddresses As New List(Of String)

EmailAddresses.AddRange(txtEmailAddresses.Text.Split(","c))

In this example, we’re going to load the selected items from a ListBox:

Dim EmailAddresses As New List(Of String)
Dim AddressArray(lstEmails.SelectedItems.Count - 1) As String
lstEmails.SelectedItems.CopyTo(AddressArray, 0)
EmailAddresses.AddRange(AddressArray)

This routines involves a little trickery because we need a temporary string array to convert the Object types in the SelectedItems collection via the CopyTo method.

In addition to simply adding onto a list we can use the InsertRange method to place items after a particular location in the List, including the beginning, as seen here:

EmailAddresses.InsertRange(0, txtEmailAddresses.Text.Split(","c))

When we want to remove more than one item, we can use the RemoveRange method, where we can specify the starting position and the number to remove:

EmailAddresses.RemoveRange(3, 2)

If we want to remove items that match a particular criteria, we can use the RemoveAll method. This method uses a Predicate delegate:

EmailAddresses.RemoveAll(AddressOf ValidateEmailAddress)

...........

Public Function ValidateEmailAddress(ByVal emailAddress As String) As Boolean
    Dim pattern As String = "[a-z][a-z|0-9|]*([_][a-z|0-9]+)*([.][a-z|0-9]+([_][a-z|0-9]+)*)?@[a-z][a-z|0-9|]*\.([a-z][a-z|0-9]*(\.[a-z][a-z|0-9]*)?)$"
    Dim match As System.Text.RegularExpressions.Match = Regex.Match(emailAddress, pattern, RegexOptions.IgnoreCase)
    Return match.Success
End Function

(Note for the validate email function to work you’ll need to import System.Text.RegularExpressions)

Sorting

To sort the List we can use default comparison method or we can define our own sorting routine as a Delegate or as class that implements the IComparer interface. For the sake of brevity, I won’t include the sorting code here, but only give an example of how it’s called. If you would like an article with more detail on these sorting methods, please leave me a comment or contact me. Here are some example calls:

EmailAddresses.Sort(AddressOf SortEmails)
.......
Dim EmailSorter As New EmailComparer

EmailAddresses.Sort(EmailSorter)

Along the same lines as sorting is the Reverse method. This method, as you might guess, simply reverses the order in the list. You can also specify a starting position and length to reverse.

That’s is all for Part I. Part II will cover searching, conversions and enumeration functions available in the List object. As always, let me know if you found this overview article helpful by leaving 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

2 comments August 28th, 2007

Introduction To VB.NET Delegates

I read that using delegates will make you even more productiveIn my previous article, How to Use the Action and Predicate Delegates, I touched on the subject of delegates. MikeP sent me an email asking me to cover a little more general information about delegates and how to use them so I put together this article.

What is a Delegate

Essentially a delegate is a function pointer, the memory address of where a routine’s code starts in memory. If we were programming in a low level language like C/C++ we would be working with these memory positions directly. If the programmer gets these pointers wrong a crash is a common result. Fortunately for us, .NET shields us from this often dangerous complexity by encapsulating the memory address of functions in the type-safe, object oriented, delegates. The .NET Framework uses delegates a lot behind the scenes when you call a routine or an event is fired. In this article we will look at some ways to use delegates in your own code.

A Simple Delegate Example

To begin with, a Delegate is declared like this:

Private Delegate Sub WriteToDisk()
.......
Private Delegate Function UpdateFile(ByVal fileName As String) As Boolean

In this example we have two delegates, one is a sub with no parameters and the second is a function with one parameter. Now we can write our actual routines. Note that the routines we plan to use with the delegate that matches the signature of the delegate. Here are two example prototype routines for our delegates above:

Private Sub WriteUserFile()
    'code to write user file data goes here
End Sub

Private Function UpdateUserAddress(ByVal userFileName As String) As Boolean
    'code to update address field goes here
End Function

Now, use the delegate, we would use the following code:

Dim DoUpdate As UpdateFile
DoUpdate = New UpdateFile(AddressOf UpdateUserAddress)
DoUpdate.Invoke(CurrentUserFileName)

These lines would create a new delegate, set the pointer to the address of the appropriate routine and then invoke it.

When and Where To Use a Delegate

Of course, our example above is a little silly. After all, why don’t you just call the desired routine directly? In ‘real world’ coding you should only use delegates when you don’t know the function you’re going to call until the program is running. You don’t want to have the extra overhead and increase the complexity of your code by using them without a reason. So when would you use them?

One delegate trick is to use them to give access to any function from any class. For example, if you had a private function in a class, you could create a delegate of that function and pass it to another class. Under normal conditions, even if you passed in a reference to the class, the private function could not be accessed. However, by using a delegate, it can be executed. It might look something like this:

Dim DoUpdate As UpdateFile = New UpdateFile(AddressOf UpdateUserAddress)
Dim UpdateRunner As New Updater(DoUpdate)

Where “UpdateUserAddress” is a private function that’s passed to another class as a delegate.

You can even make this quite generic by using a Delegate parameter, like so:

Function UpdateAdditionalFields(ByVal routineToCall As [Delegate]) As Boolean
    routineToCall.DynamicInvoke(MyLocalData)
End Function

This is kind of risky and has some significant conversion overhead but if you need a lot of flexibility, this is a way to get it. Notice that here we use the DynamicInvoke method rather than Invoke since we don’t know exactly what we will be working with until runtime. Some additional type checking would also be in order here as well.

Another common usage of delegates is in using delegates to update a form’s user interface when threading. As you may know, you can’t update a form’s UI from a background worker thread. So, instead, you pass a delegate function to the background that can update the UI as needed. Since the delegate is actually operating in the parent’s UI thread it can do the updates without a problem.

One other way you’ll see delegates used is with Events. VB.NET already does a lot of stuff behind the scenes this way. You can leverage this to create custom events. Another is the Action, Predicate and other such methods that I mentioned in my previous article.

Multicast For More Power

A powerful feature of delegates is that you aren’t limited to pointing to just one function. The System.Delegate type has an Invocation List that holds references to the functions to be called by the delegate. This allows you to mix and match your delegate calls as needed. For our example here, let’s assume we have three functions that need to be called to update an object. Here’s how you would combine them into a delegate:

Dim Addr As New UpdateUserInfo(AddressOf UpdateAddress)
Dim Phone As New UpdateUserInfo(AddressOf UpdatePhone)
Dim Email As New UpdateUserInfo(AddressOf UpdateEmail)

Dim Updates As UpdateUserInfo = DirectCast([Delegate].Combine(Addr, Phone, Email), UpdateUserInfo)

Updates.Invoke(CurrentUser)

You can also add additional delegates to the list or remove existing ones as shown here:

Dim UserName As New UpdateUserInfo(AddressOf UpdateName)
Updates = DirectCast([Delegate].Combine(Updates, UserName), UpdateUserInfo)

.........

Updates = DirectCast([Delegate].Remove(Updates, UserName), UpdateUserInfo)

As you can imagine, using this technique can be very powerful when you want to dynamically call routines. Note that the delegates are executed synchronously in the order they were added to the list. Also, should one of the methods called encounter an exception, then the delegate operation stops at that point.

I hope this gives you some ideas on how to use Delegates in your programs. If you would like for me to get into more detail about some of the ways to use delegates in a future article or have your own ideas about how to use them, please leave a comment or send me an email.

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

6 comments August 24th, 2007

How to Use the Action and Predicate Delegates

Delegates are an important tools for drafting your applicationsHow often do you write code to manually loop through a generic list or an array using a For…Each type loop? Have you written looping code to search for a particular property of a specific object in a list? Have you wondered if there was an easier way to select a sub-list from a generic list? Many programmers will use the manual loop method to achieve these goals. However, the Action and Predicate delegates offer you an easier and more flexible way to perform these operations.

Action

An Action is a delegate routine that works with a specified object. An Action doesn’t have a return value so it’s always declared as a Sub with a single parameter of a particular type. Pretty simple, but it may be a little confusing at first glance so we’ll work through a simple example.

We start with a generic list of products that have been passed into a routine. We need to load all of the products with a subcode specified by the user into a Listbox. Our ‘old’ way of doing this would look like this:

Public Sub LoadProductList(ByVal products As List(Of InventoryItem))
    lstProducts.Items.Clear()
    For Each item As InventoryItem In products
        If cboProductSubCode.Text = item.SubCode Then
            lstProducts.Items.Add(item)
        End If
    Next
End Sub

In the example above we manually loop through the List and load the Listbox. Now, here’s the code using an Action Delegate:

Public Sub LoadProductListBox(ByVal products As List(Of InventoryItem))
    lstProducts.Items.Clear()
    products.ForEach(AddressOf LoadListBoxItems)
End Sub

Public Sub LoadListBoxItems(ByVal item As InventoryItem)
    If cboProductSubCode.Text = item.SubCode Then
        lstProducts.Items.Add(item)
    End If
End Sub

On the surface, it doesn’t seem like that much of a savings. We now have two routines instead of one, slightly larger, routine. This could impact readability of the code in some cases although it might help with more complex routines or if multiple ForEach calls were required. If we look at the performance, the Action method is slightly faster, by a factor of about 3 to 5 percent, so there is a tiny advantage there.

Where the real power of this method comes into play is where you need to pass a particular action into the routine depending upon other conditions. For example, we might want to have a different action for different types of inventory so we would pass our preferred loading routine as an Action as seen here:

......
If OnlyNewProducts Then
    LoadProductListBox(InventoryList, New Action(Of InventoryItem)(AddressOf LoadImportedProducts))
Else
    LoadProductListBox(InventoryList, New Action(Of InventoryItem)(AddressOf LoadAllProducts))
End If
......

Public Sub LoadProductListBox(ByVal products As List(Of InventoryItem), ByVal loadingAction As Action(Of InventoryItem))
    lstProducts.Items.Clear()
    products.ForEach(loadingAction)
End Sub

As you might guess, being able to pass in a delegate Action opens up a lot of possibilities.

Predicate

A Predicate is a delegate function that determines if a specified object meets a set of criteria. Like Action it has one argument, the particular type to be evaluated, and it also returns a Boolean, indicating if the object met or did not meet the selection conditions in the routine. Predicates are used in the Find functions of generic Lists. Let’s start by defining a set of criteria we want our InventoryItem objects to meet. In this case, we’re wanting products added in the past 30 days.

Function SearchForNewProducts(ByVal item As InventoryItem) As Boolean
   If DateDiff(DateInterval.Day, item.IntroductionDate, Now) < 30 Then
       Return True
   Else
       Return False
   End If
End Function

Now we use the FindAll method to get a list of inventory items using this Predicate.

Dim NewProducts As List(Of InventoryItem) = ProductList.FindAll(AddressOf SearchForNewProducts)
.
.
.

Another operation you might want to do is to see if a member of a list has a property that meets a unique criteria or you may want to just return the first or last matching item in the list. For that, you use the Find or FindLast functions. For our example, we’re going to find the first item that wildcard matches a user TextBox entry.

.....
Dim SelectedItem As InventoryItem = NewProducts.Find(AddressOf FindByDescription)
.....

Function FindByDescription(ByVal item As InventoryItem) As Boolean
    If item.Description Like (txtItemDescription.Text & "*") Then
        Return True
    Else
        Return False
    End If
End Function

The other two Find methods are FindIndex and FindLastIndex. They return the index position of the object rather than the object itself. They also have overloads where you can specify the starting position and the number of objects in the list to search. This can be useful for incremental searches of large lists.

Another nice thing about using Predicates is that we can use the same delegate function for all of the Find functions:

.....
Dim SelectedItem As InventoryItem = NewProducts.Find(AddressOf FindByDescription)
.....
Dim SelectedItem As InventoryItem = NewProducts.FindLast(AddressOf FindByDescription)
.....
Dim SelectedItem As List(Of InventoryItem) = NewProducts.FindAll(AddressOf FindByDescription)
.....
Dim ItemIndex As Integer = ProductList.FindIndex(AddressOf FindByDescription)
.....
Dim ItemIndex As Integer = ProductList.FindLastIndex(AddressOf FindByDescription)

As you can see, this can provide a lot of flexibility in your code.

I hope this article has helped you gain a better understanding of these powerful delegate methods. If you have any questions about them or anything you would like to add, please leave 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

6 comments August 23rd, 2007

Introduction To VB.NET Generic Stacks

A Wedding Cake - An example of a Last-In-First-Out Stack StructureStacks are another classic data structure. Anyone who’s taken a Computer Science 101 class has probably encountered them and if you’ve done any low level coding in C++ or assembly you’ve probably written quite a few of them. However, this data structure wasn’t seen that often in classic VB or traditional BASIC programming because of the lack of pointers in the language. But, in VB.NET, we now have the Stack class and, in Framework 2.0, the strongly typed generic Stack class so you should familiarize yourself with how a stack works.

A stack is simply a Last-In-First-Out (aka LIFO) buffer where only the topmost item is visible. It’s just the opposite of the Queue structure that was covered in a previous article. A common visual metaphor used to describe a stack is a spring loaded cafeteria plate dispenser or coin holder. The standard commands for a stack are Pop, which removes and returns the top item on the stack, and Push, which places a new item at the top of the stack. Here is a simple example:

'add a url entered in a text box
UrlStack.Push(txtUrl.Text)

...

'get next url from stack and navigate to location
wbMain.Navigate(UrlStack.Pop)

In this example, we have a stack of URLs entered by the user. As the user enters a value into the textbox, we Push it onto the stack. Later in the program, we want to use the browser control to navigate to the sites so we Pop the next URL value off the stack.

What if you want to see what the topmost value is before removing it from the stack? In that case, you use the Peek function to return the value without popping it off the stack. Here’s an example:

If UrlStack.Peek().Contains("localhost") Then

In this example, we may want to perform a few other actions if the site is local before removing the URL string from the stack.

The .NET generic stack also has the standard collection management properties and methods. To get the number of items in the collection you access the Count property. To see if an item is already in the stack, you can use the Contains function. Clear is used to empty the stack. Lastly, you can use the ToArray function to move the contents of the stack to an array of the same type. Here are some examples:

If UrlStack.Count > 0 Then
    'do something with the stack
End If

If Not UrlStack.Contains(txtUrl.Text) Then
    UrlStack.Push(txtUrl.Text)
End If

UrlStack.Clear

Dim UrlList() As String = UrlStack.ToArray()

Note that it is a good idea to check the Count property of the stack before you Pop or Peek since it will generate an InvalidOperationException if it is empty. Also, while you don’t have to worry about stack overflows like you do in C++ you should be mindful of how much memory your stack is using, particularly if you use it for large custom searches and sorts.

How can you use stacks in your code?

A common use for stacks are in complex searches. If you see your search code headed in a brute force, linear, model, step back and investigate how your code might benefit from using stacks. You can Google up many examples of how to do this or read Wikipedia articles on the various search algorithms. While they probably won’t be in VB.NET, you can probably extract the logic and use it.

Games are another area where using stacks can be quite helpful. For example, you’ll find many game map or maze building programs use stacks extensively.

If you have any questions about using Generic Stacks or if you have suggestions or examples on how you use them, please leave 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

Add comment August 22nd, 2007

Introduction to VB.NET Generic Queues

Elf with a Queue of GiftsQueues are one of the common classic data structures found in computer science. A queue is simply a First-In-First-Out (aka FIFO) buffer where new items are added to the end of the list and the item at the front of the list is processed first. Implementing one in VB hasn’t always been easy due to the lack of pointers. While there were some ways to work around this, the programming could get messy and difficult to understand. However, the Queue collection type was introduced in the original .NET Framework and now, in the .NET Framework 2.0, we now have the generic Queue class to make it a breeze to implement.

As with other .NET Generic Collection classes, the queue is a type-safe collection. This means that you must define the type of object that is to be queued and only objects of that type can be placed in the queue. Here are a few examples:

Dim NameQueue As Queue(Of String)

Dim MailQueue As Queue(Of Net.Mail.MailMessage)

Dim OrderQueue As Queue(Of OrderDetailItems)

The basic operations of a queue are enqueue and dequeue. Enqueue places a new item at the end of the queue while Dequeue removes the first item in the queue from the list and returns it to the caller. The queue automatically expands to accomidate new members. Remember that if the queue is empty that the Dequeue function will return an InvalidOperationException. Here are some simple examples:

NameQueue.Enqueue(CurrentName)

Do While MailQueue.Count > 0
    SendMail(MailQueue.Dequeue)
Loop

If you wanted to view the next item in the queue without removing it, you can use the Peek function as seen in this example:

If IsSignedUp(MailQueue.Peek.To) Then
    SendMarketingEmail(MailQueue.Dequeue)
Else
    SendSignUpEmail(MailQueue.Dequeue)
End If

To further manage the Queue there is the Clear command that removes all of the contents of the Queue and the Count property to get the current number of items in the queue. There is also the Contains function that you can use to find out if a particular item is already in the queue. For example:

If Not FileNameQueue.Contains(NewFileName) Then
    FileNameQueue.Enqueue(NewFileName)
End If

One feature that you might find helpful at times is the ability to copy the Queue to an Array as seen here:

Dim MailList() As Net.Mail.MailMessage = MailQueue.ToArray()

That covers the basics of the .NET Generic Queue but maybe you’re wondering when you should use a queue?

I’ve found them particularly useful for situations where I had longer operations to process, such as parsing or converting a large datafile. For example, if I had files arriving in a FTP folder I would use FileSystemWatcher to detect the files as they arrived and place them in the queue. Then, at some point, such as every 30 minutes, the current items in the queue would be processed in the order they arrived and a new queue would be started.

Another example would be having a central order system prepare a queue of items for a remote fulfillment centers. The fulfillment center system would retrieve a serialized queue of orders via a web service from the order location’s web site and then work through the order objects within it.

If you have any questions about using Generic Queues or if you have suggestions or examples on how you use them, please leave 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

2 comments August 21st, 2007

Next Posts Previous Posts


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