Reputation: 39
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
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