Davep1553
Davep1553

Reputation: 39

Is object a dictionary of any TKey and TValue (not get TKey and TValue)

Hopefully this hasn't been answered somewhere but I really have no idea what to search for.

I have a variable that's only defined as object (I know I know avoid this)

I'm trying to determine what it is at run time so I can branch to the correct handler. To do this I'm using GetType with a Select Case

Select Case obj.GetType()
    Case GetType(String)
        'do something
    Case GetType(Integer)
        'do something
    Case Else
        'throw an error
End Select

and that works nicely. Problem is it could also be a dictionary. I need to know if it's dictionary regadless of what generic was used to define the dictionary. I'll figure out what that was in the handler.

Case GetType(Dictionary(of Object, Object))

This only hits if it's literally a Dictionary(of Object, Object), I want a case that will also hit for a Dictionary(of String, Object), or a Dictionary(of String, String), or a Dictionary(of String, Dictionary(of String, Integer)) ... etc.

I'm worried somebody will think I'm trying to determine what the TValue or TKey is so to restate, I want to match it's a dictionary of anything, I'll figure out what the "anything" is latter but first I want to know if it's even a dictionary.

Thanks in advance.

Upvotes: 0

Views: 65

Answers (1)

jmcilhinney
jmcilhinney

Reputation: 54427

There may well be a better way but here's something that will work:

Dim t = obj.GetType()

If t.IsGenericType AndAlso
   t.GetGenericTypeDefinition().FullName = "System.Collections.Generic.Dictionary`2" Then

EDIT:

Actually, there is a better way:

If t.IsGenericType AndAlso
   t.GetGenericTypeDefinition() Is GetType(Dictionary(Of ,)) Then

You can omit the generic type parameters when using GetType but that will create a generic type definition that will not match any specific Dictionary(Of TKey, TValue) type, so you can't just add this to your Select Case:

Case GetType(Dictionary(Of ,))

EDIT 2:

I just threw this extension method together that may be useful:

Imports System.Runtime.CompilerServices

Public Module TypeExtensions

    <Extension>
    Public Function MatchesGenericType(source As Type, genericType As Type) As Boolean
        If genericType Is Nothing Then
            Throw New ArgumentNullException(NameOf(genericType))
        End If

        If Not genericType.IsGenericType Then
            Throw New ArgumentException("Value must be a generic type or generic type definition.", NameOf(genericType))
        End If

        Return source.IsGenericType AndAlso
               (source Is genericType OrElse
                source.GetGenericTypeDefinition() Is genericType)
    End Function

End Module

Sample usage:

Module Module1

    Sub Main()
        Dim testTypes = {GetType(String),
                         GetType(List(Of )),
                         GetType(List(Of String)),
                         GetType(Dictionary(Of ,)),
                         GetType(Dictionary(Of String, String))}
        Dim comparisonTypes = {Nothing,
                               GetType(String),
                               GetType(List(Of )),
                               GetType(List(Of String)),
                               GetType(Dictionary(Of ,)),
                               GetType(Dictionary(Of String, String))}

        For Each testType In testTypes
            For Each comparisonType In comparisonTypes
                Console.Write($"Comparing type '{testType.Name}' to {If(comparisonType?.IsGenericTypeDefinition, "type definition", "type")} '{comparisonType?.Name}': ")

                Try
                    Console.WriteLine(testType.MatchesGenericType(comparisonType))
                Catch ex As Exception
                    Console.WriteLine(ex.Message)
                End Try
            Next
        Next

        Console.ReadLine()
    End Sub

End Module

Examples:

GetType(Dictionary(Of String, String)).MatchesGenericType(Nothing) 'Throws exception
GetType(Dictionary(Of String, String)).MatchesGenericType(GetType(String)) 'Throws exception
GetType(Dictionary(Of String, String)).MatchesGenericType(GetType(List(Of String))) 'Returns False
GetType(Dictionary(Of String, String)).MatchesGenericType(GetType(Dictionary(Of String, String))) 'Returns True
GetType(Dictionary(Of String, String)).MatchesGenericType(GetType(Dictionary(Of ,))) 'Returns True
GetType(Dictionary(Of ,)).MatchesGenericType(GetType(Dictionary(Of String, String))) 'Returns False
GetType(Dictionary(Of ,)).MatchesGenericType(GetType(Dictionary(Of ,))) 'Returns True

Upvotes: 1

Related Questions