Method for populating ListViewSubItems This is my current method for populating the sub-items of ListView controls. I like this method for two reasons... 

1) I don't have to keep up with the display order of the columns.

2) If I enable column re-ordering, I don't have to change anything with the code. 

So, the question is... Is this a good approach? Can it be improved?

Note: I'm not too happy about declaring Result As Object. It seems like there should be a better way to handle that, but it's the only way I could get it to working.

Private Function RetrieveItem(Of T)(ByVal displayIndex As Integer) As T
    Dim Result As Object = If(GetType(T) Is GetType(ListViewItem), New ListViewItem, New ListViewItem.ListViewSubItem)
    Select Case displayIndex
        Case ColumnHeader1.DisplayIndex
            Result.Text = "First Item"
            Result.Tag = "First"
        Case (ColumnHeader2.DisplayIndex)
            Result.Text = "Second Column"
            Result.Tag = "Second"
        Case ColumnHeader3.DisplayIndex
            Result.Text = "Third Column"
            Result.Tag = "Third"
        Case ColumnHeader4.DisplayIndex
            Result.Text = "Fourth Column"
            Result.Tag = "Fourth"
    End Select
    Return Result
End Function


Example Usage... 

Dim item As ListViewItem = RetrieveItem(Of ListViewItem)(0)
For i As Integer = 1 To ListView1.Columns.Count - 1
    item.SubItems.Add(RetrieveItem(Of ListViewItem.ListViewSubItem)(i))
Next
ListView1.Items.Add(item)




Here is the example I came up with using @MarkHurd's suggestion of using a Widening CType Operator... 

Private Class LVI
    Public Name As String
    Public Text As String
    Public Tag As Object
    Public Sub New(ByVal name As String, ByVal text As String, ByVal tag As Object)
        Me.Name = name
        Me.Text = text
        Me.Tag = tag
    End Sub
    Public Shared Widening Operator CType(ByVal item As LVI) As ListViewItem
        Dim Result As New ListViewItem(item.Text)
        Result.Name = item.Name
        Result.Tag = item.Tag
        Return Result
    End Operator
    Public Shared Widening Operator CType(ByVal item As LVI) As ListViewItem.ListViewSubItem
        Dim Result As New ListViewItem.ListViewSubItem
        Result.Text = item.Text
        Result.Name = item.Name
        Result.Tag = item.Tag
        Return Result
    End Operator
End Class

Private Function RetrieveItem(ByVal index As Integer) As LVI
    Select Case index
        Case ColumnHeader1.DisplayIndex : Return New LVI("1", "First Column", "one")
        Case ColumnHeader2.DisplayIndex : Return New LVI("2", "Second Column", "two")
        Case ColumnHeader3.DisplayIndex : Return New LVI("3", "Third Column", "three")
        Case ColumnHeader4.DisplayIndex : Return New LVI("4", "Fourth Column", "four")
        Case Else : Return Nothing
    End Select
End Function


Example usage...

Dim item As ListViewItem = RetrieveItem(0)
For i As Integer = 1 To ListView1.Columns.Count - 1
    item.SubItems.Add(RetrieveItem(i))
Next
ListView1.Items.Add(item)


I like both of these approaches, but I feel like the first is shorter and easier to implement, so I lean towards the first option.
If you want to avoid the late bound .Text and .Tag you could just create your own private type, say LVI, containing these two properties and implicit Widening CType operators for ListViewItem and ListViewItem.ListViewSubItem. Then the Result As New LVI can be converted on return using Return CType(CTypeDynamic(Result, GetType(T)), T) in the latest VB.NET.

Without CTypeDynamic I don't have a working solution yet.