Tip 4: Searching with .NET Generics and (Optionally) Anonymous Methods
The .NET generics List class exposes methods to perform a
Find,
FindAll, and
FindLast. I can write an anonymous method to implement my own search logic in-line as shown below, or I can build a class that serves as a Predicate (a Boolean-valued function) for the Find methods (see
Listing 1 and
Listing 2).
private void TestFindBaseballClass()
{
List<BaseballClass> oBaseball = new List<BaseballClass>();
oBaseball = this.PopulateBaseballClass();
string cSearch = "Astros";
BaseballClass oSingleFind =
oBaseball.Find( delegate(BaseballClass f1)
{ return f1.Team == cSearch; });
MessageBox.Show("Single find is " + oSingleFind);
string cResults = "";
foreach (BaseballClass oRecord in
oBaseball.FindAll( (delegate(BaseballClass f1)
{ return f1.Team == cSearch; })))
cResults += oRecord + "\r\n";
MessageBox.Show("Multiple find is " + oSingleFind);
}
The preceding code uses the same technique as the previous example: An in-line method sets up a delegate to search the populated Baseball class for the first instance of a match. Note that I could use different string functions inside the anonymous method if I wanted to implement a partial string search instead of an exact match.
I can also use the
FindAll method of the List class in the same manner. I've specified an in-line delegate and an anonymous method to return a Boolean for each incoming BaseballClass object that equals the search string. The
FindAll method allows me to implement filtering capabilities that ADO.NET provides with the DataTable object.
string cSearch = "Astros";
// Perform a single search on the first hit
BaseballClass oSingleFind = oBaseball.Find(
delegate(BaseballClass f1) {
return f1.Team == cSearch; });
// Perform a find all (almost like a filter)
string cResults = "";
foreach (BaseballClass oRecord in
oBaseball.FindAll((delegate(BaseballClass f1) {
return f1.Team == cSearch; })))
cResults += oRecord + "\r\n";
For those who prefer to write a separate class (or are using VB.NET, which does not support anonymous methods in Visual Studio 2005),
Listing 1 and
Listing 2 demonstrate a separate Find class and a code sample for using the Find class.
Tip 5: Using the List Class to Store Other Objects
As stated earlier, I can use the new List class to store any .NET type that I wish.
Listing 3 contains an example that stores classes that implement an interface. Suppose I have report classes that all contain a method called
GenerateDocument. I can set up a master controlling loop structure that does the following:
- Define an interface called IDocument that contains one method, GenerateDocument
- Build multiple report document classes (SimpleClass1, SimpleClass2, etc.) that implement IDocument
- Instantiate a List object that stores classes that implement the IDocument interface
List<SimpleInterface.IDocument> oList =
new List<SimpleInterface.IDocument>();
- Create instances of the report document classes (SimpleClass1, etc.) and add the instances to the list
- Loop through the list and call the GenerateDocument method
foreach(SimpleInterface.IDocument oClass in oList)
oClass.GenerateDocument();
Special thanks to Rob Hale from GE Healthcare for this one. Rob attended my C# 2.0 session at Boston CodeCamp and came up with the idea for this one. Two thumbs up, Rob!
Tip 6: Other Classes in the Generics Namespace
I've focused on the new List class in Visual Studio 2005. Now I want to talk about three other classes in the System.Collections.Generics namespace to be aware of. Let's take a moment and look at the new Dictionary, SortedDictionary, and Collection classes.
Visual Studio 2005 introduces the new Dictionary class. This abstract class allows developers to map keys and elements in a collection. Some functions in the .NET 2.0 Framework use the Dictionary class: One example is one of the new overloads for creating a new TCP channel. In the example below, I create a new dictionary object and specify that both the key and value will contain a string.
// Create a new dictionary object with two strings
Dictionary<string, string> oDict =
new Dictionary<string, string>();
oDict.Add("secure", "true");
oDict.Add("password", "kevin");
TcpChannel oChannel = new TcpChannel(oDict, null, null);
If you need to sort the dictionary entries by key, you'll be better off using the new SortedDictionary class, which maintains a sort order on key.
Next, while I've used the new List class, Visual Studio 2005 also offers a lightweight Collection class for simple lists that don't require sorting and filtering capabilities.
Collection<int> oCol = new Collection<int>();
oCol.Add(2);
oCol.Add(3);
oCol.Insert(0,1);
I can also store custom classes into the Collection object.
Collection<BaseballClass> oBaseballCollection =
new Collection<BaseballClass>();
oBaseballCollection.Add(
new BaseballClass("Tom Glavine","Mets"));
oBaseballCollection.Add(
new BaseballClass("Derek Jeter","Yankees"));
foreach (BaseballClass oBaseball in
oBaseballCollection)
MessageBox.Show(oBaseball.ToString());
Finally, .NET generics offers other classes, such as a LinkedList and LinkedListNote, for working with linked list data, as well as a Queue and Stack class.