Blog - Title

Using Nominal Types for Tuples - VB

Using Nominal Types for Tuples - VB

  • Comments 1

[Table of Contents] [Next Topic]

The following example (from the previous topic on anonymous types) shows projection of a collection of anonymous types:

This blog is inactive.
New blog: EricWhite.com/blog

Blog TOC

Dim custList() As Customer = { _
    New Customer With { _
        .Name = "Bob", _
        .Address = "123 Main Street, Seattle, WA 98111", _
        .Phone = "555-1234" _
    }, _
    New Customer With { _
        .Name = "Bill", _
        .Address = "555 Center Street, Tacoma, WA 97158", _
        .Phone = "555-9999" _
    } _
}
Dim newCustList = _
    custList.Select( _
        Function(c) New With { _
            .UCName = c.Name.ToUpper, _
            .UCAddress = c.Address.ToUpper _
        } _
    )
For Each c In newCustList
    Console.WriteLine(c.UCName)
Next
 

However, one problem with this code is that as written, we can't move the query into its own method.

A different approach, which I like more, is to define a named type for the tuple.  In C#, a convenient syntax is the automatic properties syntax, which allows you to define a type in a very few lines.  VB doesn’t have an equivalent feature.  However, you can gain the same expressiveness and succinctness by using public fields.  If you are using these types only for tuples, and only within a limited scope, I don’t have a problem with this approach.  Using this approach, you can define a class with n fields in n+2 lines of code.  The syntactic noise is kept to a minimum.  Depending on the circumstances, you can declare the tuple class as a nested class.

One of the characteristics of dynamic languages is the ability to add new properties to a tuple type very easily.  This characteristic is shared by VB when projecting using anonymous types.  However, I find that I have the same type of experience when using named types in the fashion described in this topic.  I don't find it particularly onerous to add new fields to the tuple type.  I have a little macro that creates one for me, and all I need to type are the type and the name.  The malleability of tuple types is nearly as good as when using a dynamic type, except that you get strong typing, and a good Intellisense experience in VS.

Consider the following code, where the tuple is defined using a private named class, and the query and projection are refactored into a separate method.

Public Class Customer
    Private m_name As String
    Private m_address As String
    Private m_phone As String
    Public Property Name() As String
        Get
            Return m_name
        End Get
        Set(ByVal value As String)
            m_name = value
        End Set
    End Property
    Public Property Address() As String
        Get
            Return m_address
        End Get
        Set(ByVal value As String)
            m_address = value
        End Set
    End Property
    Public Property Phone() As String
        Get
            Return m_phone
        End Get
        Set(ByVal value As String)
            m_phone = value
        End Set
    End Property
End Class
 
Module Module1
    Private Class UCCustomer
        Public UCName As String
        Public UCAddress As String
        Public Phone As String
    End Class
 
    Private Function ProjectUC(ByVal source As IEnumerable(Of Customer)) As IEnumerable(Of UCCustomer)
        Return source.Select(Function(c) New UCCustomer With { _
            .UCName = c.Name.ToUpper, _
            .UCAddress = c.Address.ToUpper _
            })
    End Function
 
    Sub Main()
        Dim custList() As Customer = { _
            New Customer With { _
                .Name = "Bob", _
                .Address = "123 Main Street, Seattle, WA 98111", _
                .Phone = "555-1234" _
            }, _
            New Customer With { _
                .Name = "Bill", _
                .Address = "555 Center Street, Tacoma, WA 97158", _
                .Phone = "555-9999" _
            } _
        }
        Dim newCustList = ProjectUC(custList)
        For Each c In newCustList
            Console.WriteLine(c.UCName)
        Next
    End Sub
End Module
 

Notice in the above code that the object initializer for the tuple type is nearly identical to the object initializer when projecting an anonymous type.  The only difference is the naming of the type in the initializer.

When writing queries on the fly, anonymous types are handy.

Sometimes I'll expose the nominal tuple type as a public class, and it becomes part of the programming interface to the classes and methods that contain my FP code.  For an example of this approach (in C#), see Open XML SDK and LINQ to XML.

[Table of Contents] [Next Topic] [Blog Map]

Attachment: Examples.txt
Leave a Comment
  • Please add 5 and 1 and type the answer here:
  • Post
  • Of course, with VB10, you will be able to define full-blown properties with single lines instead of needing to use public fields.

Page 1 of 1 (1 items)