Posts filed under 'VB.NET Tutorials'
To continue our review of the generic collection classes, we’ll look at the basics of the Dictionary class and how to use it.
What is a Generic Dictionary?
The generic Dictionary class is a class that maps a set of keys, which can be of any specified type, to a set of values, which also can be of any specified type. The types don’t have be the same for both the key and the value.
Perhaps, if you used VB6, you noticed the Dictionary object. Maybe you used it but many VB6′ers avoided it because it was located in the poor performing Scripting runtime. However, don’t let that ancient history put you off when it comes to the .NET generic Dictionary. This object, which uses internal hash tables, is very fast.
Dictionary Basics
To create a dictionary object, you declare it with the key type first, followed by the value type as seen in these example declarations:
Dim EmailList As New Dictionary(Of String, System.Net.Mail.MailMessage)
.....
Dim Users As New Dictionary(Of Integer, User)
.....
Dim Products As New Dictionary(Of Guid, Product)
To add to the Dictionary, you use the add command where you provide a key and a value, as seen here:
For Each Recipient As String In lstEmails.Items
If Not EmailList.ContainsKey(Recipient) Then
EmailList.Add(Recipient, CreateNewMail(Recipient))
End If
Next
If the specified key already exists in the Dictionary trying to add it again will throw an exception. Therefore, you should use the ContainsKey function to check the collection prior to adding to it, as shown above. Also note that the key can’t be Nothing.
To remove an item, you use the Remove method and provide the key:
EmailList.Remove(txtUserEmail.Text)
Don’t worry, if the item to be removed isn’t in the Dictionary, you won’t get an exception. If it isn’t there a False value is returned.
The items are stored as KeyValuePair objects of the specified types. To retrieve the items in the list individually, you use the Item property where you provide the key and the function returns the value object:
EmailServer.SendAsync(EmailList.Item(txtUserEmail.Text), String.Empty)
You can also enumerate through the list of items. This returns a KeyValuePair object, not the value object, so don’t get confused here (some people do). Here’s an example:
For Each EmailPair As KeyValuePair(Of String, System.Net.Mail.MailMessage) In EmailList
EmailServer.SendAsync(EmailPair.Value, String.Empty)
Next
.
.
.
You may also update an item in the Dictionary through the Item property:
EmailList.Item(txtUserEmail.Text) = GetHolidayEMail()
Lastly, the Clear method removes all of the keys and values from the Dictionary
Looking at the Contents
As mentioned above, you can use the ContainsKey function to determine if a particular key exists in the Dictionary. There is also the companion function, ContainsValue, that performs the same function for the values.
The TryGetValue method is another way to look up an item in the Dictionary. It combines the functionality of the ContainsKey function and Item property. This method is essentially a helper function that helps you avoid having to catch “Key Not Found” exceptions or doing additional If blocks. Here’s an example of how this method works:
Dim HolidayMailer As System.Net.Mail.MailMessage
For Each Recipient As String In lstEmails.Items
If EmailList.TryGetValue(Recipient, HolidayMailer) Then
EmailServer.SendAsync(HolidayMailer, String.Empty)
End If
Next
In some cases, you might want to extract just the keys or just the values from a dictionary. For example, you may want to get the keys and put them in a ListBox. The Dictionary exposes both as collections in the Keys and Values collections. These are special collection types and they aren’t static copies, but, instead they’re tied back to the Dictionary. Therefore, you should be careful about changing data in them. If you need to simply extract and work with the data separately, you can use the CopyTo function, as seen in this example:
Dim EmailKeys(EmailList.Keys.Count) As String
EmailList.Keys.CopyTo(EmailKeys, 0)
lstEmails.Items.AddRange(EmailKeys)
Using Comparison
The Dictionary also allows us to define how we want to determine if a particular key meets equality conditions. For example, let’s assume that you have a Dictionary where you don’t want to have to worry about the case of a key string. You want it to match if the user enters “Smith”, “smith” or even “SMitH”. To do this, we would use a .NET StringComparer as shown here:
Dim HolidayGreetings As New Dictionary(Of String, String)(StringComparer.CurrentCultureIgnoreCase)
.
.
.
Of course, for more complex comparisons, you can code your own comparer but that’s something for another article some other time.
I hope you found this article helpful. Please let me know by leaving a comment or using the rating stars. If you have a question or if you have a subject area you would like for me to cover in more detail, also either leave a comment or use the Contact Me menu button to send me an email.
Share This Article:
These icons link to social bookmarking sites where readers can share and discover new web pages.
September 5th, 2007
In my previous article, 5 Elements of Style For Error Messages, I mentioned you could use the ErrorProvider component to help the user solve a problem by providing an indicator icon and tooltip. In this article, we’ll go over how to use this component.
Why Use ErrorProvider?
It was typical in older applications for a programmer to use a message box to indicate an error condition. This had several problems. First, it interrupted the flow of the program with a modal dialog. Second, it wasn’t easy to indicate exactly which field needed to be corrected. Third, it was tricky to use for multiple entry errors.
What was needed was a better way to validate fields and provide instant feedback to the user as they worked. Some programmers coded this for themselves. Now, the ErrorProvider component does a lot, but not all, of this work for you.
The Basics
The ErrorProvider is simply an indicator for the user in the form of an icon that’s positioned next to a target control. The icon may flash, if desired, and when the user hovers over the icon a tooltip message that describes the problem should appear.
The component is usually found in the Components section of the Visual Studio toolbox. To use it, simply drag it anywhere onto the target form. Since it’s a component, it will reside in the component bar at the bottom of the form designer screen.
The error icon defaults to an exclamation point icon although you can change this if you wish. In the example below, I’ve replaced the default exclamation icon with a friendlier arrow icon. You can also set the icon to blink or not blink. My preference is to not blink.
You can use the SetIconAlignment property to position the error icon relative to the specified control. You can also set the padding value in pixels on a control-by-control basis. This is handy if you need some extra space.
To set an error for a control, you use the SetError method, passing in the control and the error message string. You can clear the error by sending in a blank string. Here’s an example of both.
erpMain.SetError(txtEntry, "This is an error!")
.....
erpMain.SetError(txtEntry, "") 'clear error
The matching GetError method allows you to get the specific error assigned to a control. You can use the Clear method to remove all of the currently set error conditions in the object. Unfortunately, this collection of controls and errors isn’t otherwise exposed for you to manipulate.
The ErrorProvider can be used with bound or unbound controls. In this example, I won’t be covering the databinding portion of this component.
The Sample Program
In this example, we’ll use a simple user login setup dialog that an administrative user might use to add a new user or edit an existing user. Our requirements for the form are:
A user name field that must be between 8 and 25 characters
A password field that is between 8 and 20 characters long, that contains at least one upper case letter, one lower case letters, and one numbers or special characters, that uses a password mask character, and that must be entered twice for verification.
An Email address field that should be in a valid email address format but should not be more than 50 characters
Here is the basic design:

To meet the maximum length requirements, we’ll simply set the MaxLength property of our textboxes to match. This eliminates the need to check this part of entry. Another trick I like to use is to disable the OK button until all of the entry fields contain valid data. We will see this in action later.
Now, we will need to code our form. To begin with, we will want to set the position of the error provider icon for each control that we want to validate and set the default state. We’ll do this in the Form Load event:
Private Sub frmLoginSetup_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
With erpLoginSetup
.SetIconAlignment(txtUserName, ErrorIconAlignment.MiddleRight)
.SetIconAlignment(txtPassword, ErrorIconAlignment.MiddleRight)
.SetIconAlignment(txtRepeatPassword, ErrorIconAlignment.MiddleRight)
.SetIconAlignment(txtEmail, ErrorIconAlignment.MiddleRight)
End With
'Set the initial state of the error provider
txtUserName_TextChanged(txtUserName, New System.EventArgs)
txtPassword_TextChanged(txtPassword, New System.EventArgs)
txtPassword_TextChanged(txtRepeatPassword, New System.EventArgs)
txtEmail_TextChanged(txtEmail, New System.EventArgs)
End Sub
Next, we will create our validation code. We will begin with the User Name textbox in its TextChanged event:
Private Sub txtUserName_TextChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles txtUserName.TextChanged
If txtUserName.Text.Length < 8 Then
erpLoginSetup.SetError(txtUserName, "User Name must be at least 8 characters long")
Else
erpLoginSetup.SetError(txtUserName, "")
End If
EntriesOK()
End Sub
Now we’ll add code for the password checking. This code is more complex since we’re routing events from both password textboxes through this routine. Note that we’re using a regular expression to test for our strong password so we will want to include an Imports System.Text.RegularExpressions statement at the top of our form module.
Private Sub txtPassword_TextChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles txtPassword.TextChanged, txtRepeatPassword.TextChanged
Dim txtPwd As TextBox = DirectCast(sender, TextBox)
If txtPwd.Text.Length < 8 Then
erpLoginSetup.SetError(txtPwd, "Password must be at least 8 characters long")
Else
If Regex.IsMatch(txtPwd.Text, "(?=^.{8,}$)((?=.*\d)|(?=.*\W+))(?![.\n])(?=.*[A-Z])(?=.*[a-z]).*$") Then
If txtPassword.Text = txtRepeatPassword.Text Then
erpLoginSetup.SetError(txtPassword, "")
erpLoginSetup.SetError(txtRepeatPassword, "")
Else
If txtPwd.Name = "txtPassword" Then
erpLoginSetup.SetError(txtPassword, "")
erpLoginSetup.SetError(txtRepeatPassword, "Password fields must match.")
Else
erpLoginSetup.SetError(txtPassword, "Password fields must match.")
erpLoginSetup.SetError(txtRepeatPassword, "")
End If
End If
Else
erpLoginSetup.SetError(txtPwd, "Password must contain at least 1 upper case and 1 lower case letter and at least one number or special character.")
End If
End If
EntriesOK()
End Sub
Finally, we’ll add code for the email textbox. Once again, we’re using a regular expression to validate our email address.
Private Sub txtEmail_TextChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles txtEmail.TextChanged
If Regex.IsMatch(txtEmail.Text, "[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]*)?)$") Then
erpLoginSetup.SetError(txtEmail, "")
Else
erpLoginSetup.SetError(txtEmail, "The provided email address is not a valid email address.")
End If
EntriesOK()
End Sub
Our last routine checks to see if any errors are outstanding. If there aren’t any, it enables the OK button, if there are errors, the button is disabled. This routine should be called from the Text_Changed events that set or clear the provider’s error.
Private Sub EntriesOK()
If erpLoginSetup.GetError(txtUserName).Length = 0 AndAlso _
erpLoginSetup.GetError(txtPassword).Length = 0 AndAlso _
erpLoginSetup.GetError(txtRepeatPassword).Length = 0 AndAlso _
erpLoginSetup.GetError(txtEmail).Length = 0 Then
btnOK.Enabled = True
Else
btnOK.Enabled = False
End If
End Sub
You can download the code for this project here: ErrorProviderDemo Code Example
That covers this example of using the ErrorProvider component. Let me know if you found this article and example helpful or if you have any questions about it by leaving a comment.
Share This Article:
These icons link to social bookmarking sites where readers can share and discover new web pages.
September 4th, 2007
If you’ve been around VB a while you know that concatenating strings, particularly large strings over about 1K, can be a time consuming task for your applications. To deal with this, Microsoft introduced the StringBuilder class in the .NET Framework in the System.Text Namespace. In this article we’ll look at the advantages of using it and go over some of the fundamentals of using it.
Why Use StringBuilder?
You still see a lot of code around that uses the old string concatination methods. That’s not surprising because it’s comfortable and familiar to use for most VB’ers. But, there are two good reasons to use StringBuilder for large or looped string concatenation operations: speed and readability.
Speed is really a no-brainer. Using StringBuilder averages around 10 times faster than the concatenation operator ‘&’ or the String.ConCat function. It’s highly optimized for fast string operations. Even C++ .NET programmers have trouble outperforming it.
Readability is the other advantage. How often have you seen, or even written, code like this:
sSQL = "UPDATE Profile " & _
"SET FName='" & txtFName.Text & "', " & _
"MName='" & txtMName.Text & "', " & _
"LName ='" & txtLName.Text & "', " & _
"NickName='" & txtNickname.Text & "', " & _
"Address='" & txtAddress.Text & "', " & _
"Phone='" & txtPhone.Text & "', " & _
"Email='" & txtEmail.Text & "', " & _
"Status='" & cboStatus.Text & "', " & _
"Notes='" & txtNotes.Text & " " & _
"WHERE (ProfileID = " & txtProfileID.Text & ");"
or code like this
sSQL = "UPDATE Profile "
sSQL = sSQL & "SET FName='" & txtFName.Text & "', "
sSQL = sSQL & "MName='" & txtMName.Text & "', "
sSQL = sSQL & "LName = '" & txtLName.Text & "', "
sSQL = sSQL & "NickName = '" & txtNickname.Text & "', "
sSQL = sSQL & "Address = '" & txtAddress.Text & "', "
sSQL = sSQL & "Phone ='" & txtPhone.Text & "', "
sSQL = sSQL & "Email='" & txtEmail.Text & "', "
sSQL = sSQL & "Status= '" & cboStatus.Text & "', "
sSQL = sSQL & "Notes='" & txtNotes.Text & " "
sSQL = sSQL & "WHERE (ProfileID = " & txtProfileID.Text & ");"
This code is usually difficult to read and even more difficult to debug, especially if it goes on for 20, 30 or even 50+ lines like I’ve seen some code. It can even be difficult to code this originally since it’s quite easy to mistype something.
Append, AppendLine, and AppendFormat
We’ll begin looking at StringBuilder by taking a look at how we could build the same SQL statement above using StringBuilder and then taking a look at the Append commands. (Note that I don’t recommend building SQL statements dynamically like this due to SQL injection risks but it’s a good common string building example.)
Here’s the StringBuilder code:
Dim SqlBuilder As New System.Text.StringBuilder
With SqlBuilder
.Append("UPDATE Profile ")
.AppendFormat("SET FName='{0}', ", txtFName.Text)
.AppendFormat("MName='{0}', ", txtMName.Text)
.AppendFormat("LName='{0}', ", txtLName.Text)
.AppendFormat("NickName='{0}', ", txtNickname.Text)
.AppendFormat("Address='{0}', ", txtAddress.Text)
.AppendFormat("Phone='{0}', ", txtPhone.Text)
.AppendFormat("Email='{0}', ", txtEmail.Text)
.AppendFormat("Status='{0}', ", cboStatus.Text)
.AppendFormat("Notes='{0}' ", txtNotes.Text)
.AppendFormat("WHERE (ProfileID = {0}); ", txtProfileID.Text)
End With
That’s a lot cleaner and easier to read, isn’t it? Now let’s look at the Append commands.
The Append function adds the specified value to the end of the builder. One neat thing about Append is that it not only takes a string argument but it has 19 overloads that allow you to append the major data types (Int, Long, etc.), a substring of a specified string, or the default .ToString value of an object. This makes it very powerful and easy to use as compared to standard concatenations that require type conversion (if you’re running Option Strict like you should be doing). Since it does the type conversions for you internally, this helps even more with the speed.
AppendFormat also adds the specified value to the end but also applies a format to it. In the example above, we’re using a custom format string for each line of the SQL statement that allows us to insert the value into the single quoted location without additional concatenation overhead. This method also accepts objects and does the conversion internally as part of the formatting logic.
The AppendLine adds the ‘default line terminator’, aka the CR/LF pair on all Windows systems, to the end of the builder. Optionally, you may also include a string as seen here:
With EmailBuilder
.AppendLine()
.AppendLine("Sincerely,")
.AppendLine()
.AppendLine(txtSignatureName.text)
End With
Oh, just in case you didn’t know, the standard .ToString method allows you to retrieve the internal string from StringBuilder. Also note that I like to use With blocks for it since it makes it easier to read, for me anyway.
Insert
Insert is a lot like Append in that it has overloads for most data types. However, with it, you can specify where in the character sequence the string (or string representation of an object) goes. A limitation of Insert is that unless you get the string that’s being built using the .ToString method and use the IndexOf method on the result you can’t get the position where you want to insert. This limits its usefulness a bit but it can be quick if you need to insert a hunk of text in the middle of a large string as seen in this example:
' Email built using a template
If txtPersonalMessage.Text.Length > 0 Then
EmailBuilder.Insert(EmailBuilder.ToString.LastIndexOf("Sincerely,") - 1, txtPersonalMessage.Text)
End If
Replace
Replace, as the name implies, allows you to replace a given string with another string. This is especially powerful for templating applications when you can replace a key value in the template with a value from a database query or a business object as shown in this example:
With EmailBuilder
.Replace("{customer_fullname}", CurrentCustomer.FullName)
.Replace("{customer_firstname}", CurrentCustomer.FirstName)
.Replace("{customer_city}", CurrentCustomer.City)
'more replacements after this
End With
Remove
Remove, as you might expect, allows you to remove a specified number of characters starting at a particular position. Once again, finding the position is a little tricky. It can be useful if you need to remove a paragraph from a template, as in this example:
'we're assuming we already have the position info we need
EmailBuilder.Remove(HolidayGreetingIndex, HolidayGreeting.Length)
That wraps up the basics of using the StringBuilder class. I hope you’ve found this article helpful in learning about this class and how to use it. Let me know if you liked this article or have comments/question by leaving a comment, using the contact me button, or using the rating stars.
Share This Article:
These icons link to social bookmarking sites where readers can share and discover new web pages.
August 31st, 2007
Operator overloading has been around quite some time in object oriented languages like C++ but it’s a new feature in VB.NET with the .NET Framework 2.0. In this article, we’ll look at what operator overloading is and how we can use it in our VB.NET programs.
What is Operator Overloading?
Operator overloading is a type of polymorphism that applies to operators, like plus (+) or equals (=), and gives them different implementations. Using it you can redefine overloadable operations within your classes and structures and make your code cleaner and easier to read. It will also make it easier for you to interact with object that already expose overloaded operators.
Which VB.NET Operators Can Be Overloaded?
VB.NET allows the following operators to be overloaded:
- + (increment/plus - unary and binary)>
- - (decrement/minus - unary and binary)
- Not (unary)
- IsTrue (unary)
- IsFalse (unary)
- CType (unary)
- * (multiply - binary)
- / (divide - binary)
- \ (integer divide - binary)
- & (concatinate - binary)
- Like (binary)
- Mod (binary)
- And (binary)
- Or (binary)
- Xor (binary)
- ^ (raise to power - binary)
- << (left shift - binary)
- >> (right shift - binary)
- = (equals - binary)
- <> (not equals - binary)
- < (less than - binary)
- > (greater than - binary)
- <= (less than or equal to - binary)
- >= (greater than or equal to - binary)
Unary operators only have one argument while binary operators require two. Obvious, I know, but some novices stumble on this at first.
You don’t have to overload all of the operators in your class, just use the ones you need. However, you must include overloads for these logical pairs of comparative operators :
- = and <>
- < and >
- <= and >=
- IsTrue and IsFalse
How Do You Code It?
‘Operator’ is a method keyword just like Function and Sub. The difference is that the name you use is simply the operator as seen here:
Public Shared Operator +(ByVal message1 As EmailMessage, ByVal message2 As EmailMessage) As EmailMessage
Dim ReturnValue As New EmailMessage
'code here to combine objects into new object
Return ReturnValue
End Operator
Operators must always be declared as Shared and must always return a value. You cannot use an Exit statement with them, you must always use return. Another consideration is that the parameters or the return value must be the same as the containing class. For unary operators, the single parameter must be the containing class although the return value doesn’t have to be. For binary operators, at least one of the parameters must be the containing class.
Our code for calling the operator is quite simple, as seen here:
Dim OperationsAlertEmail As New EmailMessage
Dim SalesAlertEmail As New EmailMessage
'Build Alert Emails here
'Combine them for executive distribution
Dim ExecutiveAlertEmail As EmailMessage = OperationsAlertEmail + SalesAlertEmail
Also, you can have overloads to your binary operators. For example, let’s assume that in our example we have different classes for each type of email but we want to be able to combine them in some cases. Therefore we might have a set of overloaded operator methods like so:
Public Shared Operator +(ByVal message1 As SalesEmailMessage, ByVal message2 As ExecutiveEmailMessage) As ExecutiveEmailMessage
Dim ReturnValue As New ExecutiveEmailMessage
'code here to combine objects into new object
Return ReturnValue
End Operator
Public Shared Operator +(ByVal message1 As OperationsEmailMessage, ByVal message2 As ExecutiveEmailMessage) As ExecutiveEmailMessage
Dim ReturnValue As New ExecutiveEmailMessage
'code here to combine objects into new object
Return ReturnValue
End Operator
As mentioned above, only one of the parameters in a binary operation have to be of the containing type. This can allow you to code something like this:
Public Shared Operator &(ByVal message1 As EmailMessage, ByVal messageText As String) As String
Return message1.MessageHeader & message1.MessageText & messageText
End Operator
...................
Dim NewMessageText As String = ExecutiveAlertEmail & txtUpdatedMessage.Text
As you can see, using an overloaded operator can make it easy for your class to combine with other objects. In the example above, if the operator wasn’t there the concantination operation wouldn’t compile due to an “Operator Not Defined” error. While our example is rather simple, remember that you can expand this concept to encompass more complex solutions.
However, you do want to avoid any unnecessary complexity in your operator code. Don’t include things like database access, file access, and so forth in operator code. You want the performance of operators to be as fast as possible. Also, you want to make the operation intuitively logical as well. For example, if you have a plus operator, don’t make it subtract or divide! The bottom line is that another programmer shouldn’t have to look at your code to understand what is happening, they should be able to determine it intuitively. If they can’t, then an operator may not be the appropriate choice for that routine.
I hope you found this introduction to operator overloading informative and useful. Let me know what you think by leaving a comment or question, using the contact me button or just using the rating stars. That way I know if I’m covering is what you want to see, if it is helpful or not, or if you would like more information about a subject.
Share This Article:
These icons link to social bookmarking sites where readers can share and discover new web pages.
August 30th, 2007
In Part I, I covered the basics of the List object as well as inserting and removing items and sorting items. In this part I’ll be covering searching, conversion, and enumeration functions available in the List object.
Searching
The List object offers several powerful search methods. The first is quite simple, Contains. It searches the List to see if it contains an object that matches the parameter as seen here:
If EmailAddresses.Contains(txtEmailAddress.text) Then
If you need to have more sophisticated existence searching you can use the Exists method. It takes a Predicate Delegate so you can write your own code for this purpose:
If EmailAddresses.Exists(AddressOf AddressLoaded) Then
.............
Private Function AddressLoaded(ByVal emailAddress As String) As Boolean
If emailAddress = txtEmailAddress.Text Then
Return True
Else
Return False
End If
End Function
IndexOf and LastIndexOf return the position of the specified item in the List should you want the index rather than the specific item itself.
Next we have the Find methods (Find, FindAll, FindLast, FindIndex, FindLastIndex) that also use Predicate Delegates. I covered these delegates in my previous article, How to Use the Action and Predicate Delegates, so I won’t cover them again here.
TrueForAll is another handy Predicate Delegate based search method that will tell you if a particular condition is true for all the items in the List:
If EmailAddresses.TrueForAll(AddressOf ValidateEmailAddress) Then
Our last searching method is BinarySearch. It uses a binary search algorithm, essentially the default Comparer or one you specify, to locate a specific item in the List. Note that the list should be sorted with the same Comparer first or else it won’t work correctly. This method is particularly handy for inserting new items into a particular place in the List. I don’t have a good example of this one but if there is demand for it I’ll include it in a future article dealing with comparers.
Conversion
The List also provides us with a number of ways to convert the data within it.
The AsReadOnly returns a ReadOnlyCollection:
Dim OptOutEmails As IList(Of String) = EmailAddresses.AsReadOnly
ConvertAll takes the content of the List and, using a Converter Delegate, creates a new list with a different type of item:
Dim Emails As New List(Of System.Net.Mail.MailMessage)
Emails = EmailAddresses.ConvertAll(New Converter(Of String, System.Net.Mail.MailMessage)(AddressOf ConvertToEmailMessage))
................
Private Function ConvertToEmailMessage(ByVal emailAddress As String) As System.Net.Mail.MailMessage
'email message building code would go here
End Function
We saw the CopyTo method used above when copying a ListBox’s SelectedItems collection to a List. This CopyTo works the same way:
Dim EmailsSent(EmailAddresses.Count - 1) As String
EmailAddresses.CopyTo(EmailsSent)
Of course, it’s a lot easier to use the ToArray function to do the same thing:
Dim EmailsNotSent() As String
EmailsNotSent = EmailAddresses.ToArray
The GetRange method allows you to extract a portion of the List as a list in its own right:
Dim ProcessNow As List(Of String) = EmailAddresses.GetRange(0, EmailAddresses.Count \ 2)
.
.
.
Enumeration
As we discussed in the previous article on Actions and Predicates, ForEach uses Action Delegates to do something with each member of a List. For example:
Emails.ForEach(AddressOf SendEmail)
If you need more control, you can get the enumerator and manipulate it yourself with the GetEnumerator method.
I hope you’ve found these two overview articles helpful. If you did or didn’t please let me know by leaving a comment. It’s your feedback either through comments, contact me emails, or rating stars that help me chart the direction of this blog’s articles.
Share This Article:
These icons link to social bookmarking sites where readers can share and discover new web pages.
August 29th, 2007
Next Posts
Previous Posts