Pairs, Triplets and Delegates, Oh My
March 17th, 2007I recently discovered the Triplet class in the System.Web.UI namespace. It can be used to hold 3 values which is immensely useful when you need to hold onto a few values which are all related. In the same namespace is the Pair class which holds onto 2 values. Without these classes I have resorted to alternative means of managing collections of related data. One such alternative is holding onto multiple collections with one value in each collection. This alternative would use a collection like IDictionary<int, string> with an index to match the values across the collections. While I may get points for using Generics, the use of multiple collections is still not very elegant because I would have to manage all of those collections and ensure I keep them synchronized with each add, update and remove. (nevermind thread safety) I may have actually done this years ago but I have actively avoided it in recent years. Another alternative is to create a custom class just to hold onto these related values, but that is just more work. The Pair and Triplet classes seem to fill this need when placed in a collection, such as IDictionary<int, Pair> or IDictionary<int, Triplet>.
I have wanted to use the Triplet class since I discovered it and I thought I had come across right place to use it for the first time. I have a method which takes an integer value named productId which is used to query a database to get a product which is naturally returned as a DataSet. I am also using the SqlDependency class which will fire the OnChange event when the data from the query changes in the database. The OnChange event gives does not carry the productId value through to the event handler but instead holds onto a Guid value in the Id property. This gives me 3 values I can put together so that I can look them up when I need them. Initially I considered using List<Triplet> but that does not give me an index to quickly access the values, so I changed it to IDictionary<int, Pair> and set the productId as the index value. I could have also used the Guid value but the productId would be used more often. This approach was functional but it still seemed clumsy.
Finally I realized this would be perfect place to make use of a delegate to define an anonymous method which would handle the OnChange event. The beauty of using a delegate is the fact that I can make use of the context of the current method which already has the right productId so that I do not need the arbitrary Guid from the SqlDependency instance to look it up.
You can see the code snippets below:
These delegates are very useful. In the documentation the block of code defined here is called an anonymous method. It can also be called a closure which is a feature used heavily in Javascript and other dynamic scripting languages. In Javascript you use a closure to curry variables into an anonymous function. I am learning I can save a good deal of time with this style of coding.
