Reflecting on Generics
Determine whether an existing variable is a generic type and whether you have to use reflection in particular cases; create irregularly shaped forms; and enable remoting with single-instance applications.
by by Bill McCarthy
June 13, 2007
Technology Toolbox: VB .NET
Generics in .NET provide strong typing, high performance, and code reuse. In applications designed with generics in mind, generic parameters are passed throughout, enforcing constraints and providing the strong typing benefits. However, not all applications have the luxury of having been designed from the outset with generics in mind. Applications and frameworks written in .NET 1.0, 1.1, COM Interop, and even event-driven design still suffer from not having generic parameters available. The result is often an impedance mismatch, and gives rise to the one of the most frequent questions I get asked about generics: "How do I tell if this variable is a generic type?"
My first response to this is to question the question. Look at your code, look at your design, and see if you can factor it to either include generic parameters or to code completely without them. In the few cases where you do need to work with generic code from non-generic code, reflection allows you to build a bridge between the two.
One of the most common scenarios is trying to determine whether list items are of a particular type. For example, assume you have this class hierarchy:
Class Customer : Inherits Person
Class Employee : Inherits Person
Now assume you have a routine that is meant to process Person objects from a List, and you are passed a List(Of Customer) as an Object:
Public Sub CallingCode
Dim items as New List(Of Customer)
Public Sub ProcessPeople(ByVal items _
'work with items here
Inside the ProcessPeople method, items is As Object. Now test to see whether items is a List(Of Person):
If TypeOf items Is GetType(List(Of _
This test fails. The reason for the failure is that there is no generic variance: A List(Of Person) is not interchangeable with a List(Of Customer), even though Customer derives from Person. This is an important concept to understand when dealing with generics.
Variance would make it an easier task to test whether a List(Of Customer) is a list containing items that derive from Person, but it would also impede type safety. If the list's Item property were As Person, you could add any type to the list, as long as the type derives from Person. You would lose the type safety of ensuring that only Customers are in the list. In the future, VB and C# might get some kind of limited variance with generics, but a solution that makes it intuitive, yet preserves type safety, is some time away.
Today, the best solution for dealing with the items variable in this particular case is to refactor the method and provide a generic overload:
Public Sub ProcessPeople(Of T As Person) _
(ByVal items As List(Of T))
Back to top