Tuesday, January 7, 2020

The Useful Generic List in VB.NET

Generics extend the power and flexibility of VB.NET in a lot of areas, but you get a bigger performance benefit and more programming options in the generic List object [List(Of T)] than with any other. To use List(Of T), you have to understand how to implement the many methods that the .NET Framework provides. Below are three examples using ForEach, FindAll, and Sort, that demonstrates how the generic List class works. The very first step is to create a generic List. You can get the data in a lot of ways, but the simplest is to just Add it. The code below shows how to classify my beer and wine collection! Starting Code There first needs to be an object that will represent a bottle from the collection. In a Windows Forms application, the Form class has to first be in a file or the Visual Studio designer wont work correctly, so put this at the end: Public Class Bottle Public Brand As String Public Name As String Public Category As String Public Size As Decimal Public Sub New( _ ByVal m_Brand As String, _ ByVal m_Name As String, _ ByVal m_Category As String, _ ByVal m_Size As Decimal) Brand m_Brand Name m_Name Category m_Category Size m_Size End Sub End Class To build the collection, Add the items. This is whats in the Form Load event: Dim Cabinet As List(Of Bottle) _ New List(Of Bottle) Cabinet.Add(New Bottle( _ Castle Creek, _ Uintah Blanc, _ Wine, 750)) Cabinet.Add(New Bottle( _ Zion Canyon Brewing Company, _ Springdale Amber Ale, _ Beer, 355)) Cabinet.Add(New Bottle( _ Spanish Valley Vineyards, _ Syrah, _ Wine, 750)) Cabinet.Add(New Bottle( _ Wasatch Beers, _ Polygamy Porter, _ Beer, 355)) Cabinet.Add(New Bottle( _ Squatters Beer, _ Provo Girl Pilsner, _ Beer, 355)) All of the above code is standard code in VB.NET 1.0. However, note that by defining your own Bottle object, you get the benefits of multiple types in the same collection (in this case, both String and Decimal) and efficient, type safe late binding. ForEach Example The fun starts when we use the methods. To begin, lets implement the familiar ForEach method. The Microsoft documentation includes this usage syntax definition: Dim instance As List Dim action As Action(Of T) instance.ForEach(action) Microsoft further defines action as delegate to a method that performs an action on the object passed to it. The elements of the current List(T) are individually passed to the Action(T) delegate. Tip: For more on delegates, read Using Delegates in Visual Basic .NET for Runtime Flexibility. The first thing you need to code is the method that will be delegated. Misunderstanding this one key point is the source of most of the confusion of VB.NET students. This function, or subroutine, is where all of the customized coding for the Of type objects is done. When performed correctly, youre essentially done. Its really simple in this first example. An entire instance of the Bottle is passed and the subroutine selects anything needed out of it. Coding the ForEach itself is simple too. Just fill in the address of the delegate using the AddressOf method. Sub displayBottle(ByVal b As Bottle) ResultList.Items.Add( _ b.Brand - _ b.Name - _ b.Category - _ b.Size) End Sub Private Sub ForEachButton_Click( ... ResultList.Items.Clear() ResultList.Items.Add(For Each Example) ResultList.Items.Add(-----------------------) Cabinet.ForEach(AddressOf displayBottle) End Sub FindAll Example FindAll is a little more complicated. The Microsoft documentation for FindAll looks like this: Dim instance As List Dim match As Predicate(Of T) Dim returnValue As List(Of T) returnValue instance.FindAll(match) This syntax includes a new element, Predicate(Of T). According to Microsoft, this will represent the method that defines a set of criteria and determines whether the specified object meets those criteria. In other words, you can create any code that will find something in the list. I coded my Predicate(Of T) to find anything in the Beer Category. Instead of calling the delegate code for each item in the list, FindAll returns an entire List(T) containing only the matches that result from your Predicate(Of T). Its up to your code to both define this second List(T) and do something with it. My code just adds the items to a ListBox. Private Sub FindAllButton_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles FindAllButton.Click ResultList.Items.Clear() ResultList.Items.Add(FindAll Example) ResultList.Items.Add(-----------------------) Dim sublist As List(Of Bottle) sublist Cabinet.FindAll(AddressOf findBeer) For Each r As Bottle In sublist ResultList.Items.Add( _ r.Brand - _ r.Name - _ r.Category - _ r.Size) Next End Sub Function findBeer(ByVal b As Bottle) _ As Boolean If (b.Category Beer) Then Return True Else Return False End If End Function Sort Example The final method this article examines is Sort. Again, Microsoft uses some terminology you might not be familiar with. There are actually four different overloads of the Sort method: Sort()Sort(IComparer(T))Sort(Comparison(T))Sort(Int32, Int32, IComparer(T)) This lets you use sort methods defined in the .NET Framework for the list, code your own, use a system defined comparison for the type, or sort part of the collection using a starting position and count parameter. In this example, since I use the following syntax to actually perform the sort, Im using the third overload. x.Name.x.Name.CompareTo(y.Name)(y.Name) Ive coded another delegate to my own comparer. Since I want to sort by my Name, I pull just that value out of each instance of the Bottle object that is passed and use the Sort(Comparison(Of (T))). The Sort method actually rearranges the original List(T). Thats what is processed after the method is executed. Private Sub SortButton_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles SortButton.Click ResultList.Items.Clear() ResultList.Items.Add(Sort Example) ResultList.Items.Add(-----------------------) Cabinet.Sort(AddressOf sortCabinet) For Each r As Bottle In Cabinet ResultList.Items.Add( _ r.Name - _ r.Brand - _ r.Category - _ r.Size) Next End Sub Private Shared Function sortCabinet( _ ByVal x As Bottle, ByVal y As Bottle) As Integer Return x.Name.CompareTo(y.Name) End Function These methods were selected to demonstrate the major ways that the Framework methods in List(T) are actually coded. Theres a whole raft of other methods, however. Thats what makes List(T) so useful!

No comments:

Post a Comment

Note: Only a member of this blog may post a comment.