> ## Content Index
> Fetch the complete content index at: https://nolongerset.com/llms.txt
> Use this file to discover other available public pages before exploring further.

# Generic Objects in twinBASIC
- URL: https://nolongerset.com/generic-objects-in-twinbasic/
- Published: 2021-04-19T02:47:24.000Z
- Updated: 2026-05-08T13:05:12.000Z
- Description: twinBASIC supports generic objects! Let's dig into the details with a practical example.
- Author: Mike Wolfe
- Tags: twinBASIC, #Import 2026-05-20 02:59

*To learn more about [twinBASIC](https://www.twinbasic.com/), join me at this year's virtual [Access DevCon](https://nolongerset.com/join-me-at-access-devcon-2021/) where I will be presenting this exciting new project from vbWatchdog creator, Wayne Phillips.*

### Generic objects in twinBASIC

One of the exciting new features in the twinBASIC language is its support for generic objects. In a nutshell, generics allow you to pass *types* as parameters in addition to simply passing *values*.

This is particularly useful if you want to define a common data structure in the form of a class. The class won't care what type(s) you pass to it, so long as you are consistent with the types for a given instance of the class.

[Generic programming](https://en.wikipedia.org/wiki/Generic%5Fprogramming) can be a bit difficult to wrap your head around. Rather than spend this article discussing it, I'll let you follow that link and go down the Wikipedia rabbit hole on your own.

What I'm interested in here is showing you a quick practical example of a generic class in twinBASIC. In doing so, I hope you'll see how powerful this feature can be given the right circumstances.

## The Right Circumstances

The [Dictionary object](https://docs.microsoft.com/en-us/office/vba/language/reference/user-interface-help/dictionary-object) in the Microsoft Scripting Runtime is a [](https://en.wikipedia.org/wiki/Hash%5Ftable)[hash table](https://nolongerset.com/vba-dictionaries-aka-hash-tables/) structure that lets you store data as key-value pairs. The object is a bit unsafe, though, as the key and value are both Variant types. Because of this, you can use absolutely anything as both key and value. You can even mix types within the same instance of the class. 

This is madness. Let's put a stop to it.

## The Code

The sample below is not a full implementation of a generic dictionary class; I'll leave that as an exercise for the reader (or maybe the subject of a future article). Rather, it's just enough to demonstrate the syntax of generic objects in twinBASIC so that you can do your own experimenting.

```vba
Class Dict (Of TKey, TValue)
    Dim mDict As Scripting.Dictionary
    
    Public Sub New()
        Set mDict = New Scripting.Dictionary
    End Sub
    
    Public Sub Add(Key As TKey, Value As TValue)
        mDict.Add(Key, Value)        
    End Sub
    
    Public Property Get Item(Key As TKey) As TValue
        Return mDict.Item(Key)
    End Property
End Class
```

The new syntax that makes this whole thing work when defining a generic class is the `Class <ClassName> (Of <TypeA>, <TypeB>, <TypeC>)` declaration line. Notice that the types that we define by name in that line can then be referenced elsewhere within the class when defining properties and methods:

![](https://storage.ghost.io/c/eb/d7/ebd732c1-5f03-4f07-b386-5d08557e15c9/content/images/2021/04/2021-04-18-21_02_58-mjw20---NewProject---TWINBASIC.png)

### Naming conventions

A common naming convention is to use the single capital letter 'T' to represent the type if there is only a single type accepted by the generic class. If there are multiple types (as in our example above), the convention is to use a leading capital 'T' followed by a descriptive name for the type. 

In this case, the first type variable, `TKey`, refers to the "type of the key" our dictionary will accept. The second variable, `TValue`, refers to the "type of the value" our dictionary will accept. 

### Using the class

Let's start with a simple example. We will create a dictionary that uses a long integer for a key and a string as the value.

```vba
Sub TestDict()
    Dim Lookup As Dict(Of Long, String)
    Set Lookup = New Dict(Of Long, String)
    
    Lookup.Add 1, "A"
    Lookup.Add 5, "E"
    Lookup.Add 9, "I"
    
    Debug.Print Lookup.Item(5)
End Sub
```

Notice that we need to provide the types both when declaring the object (the `Dim Lookup` line) and when creating an instance of the object (the `Set Lookup` line).

### Reusing the class

This is where we get to see why we would write generics in the first place. Let's say we want to create a different kind of lookup table. This one will be keyed using a string. The string key will be used to retrieve an [oVehicle object](https://nolongerset.com/strongly-typed-collections-in-vba/).

```vba
Sub TestVehicleDict()
    Dim CarLookup As New Dict(Of String, oVehicle)
    
    CarLookup.Add "Bullitt", NewVehicleObject("Ford", "Mustang", 1968)
    CarLookup.Add "ECTO-1", NewVehicleObject("Cadillac", "Miller-Meteor", 1950)
    
    Debug.Print CarLookup.Item("Bullitt").Year
    Debug.Print CarLookup.Item("ECTO-1").Model
End Sub
```

In this example, we used the `As New` syntax to automatically generate an instance of the variable the first time it is referenced. This works just as well with our generic object as the `Dim`/`Set` approach we took in the previous example.

And just to prove that the compiler is actually enforcing the type safety, let's try calling `CarLookup.Add()` with the same arguments we used to call `Lookup.Add()`:

![](https://storage.ghost.io/c/eb/d7/ebd732c1-5f03-4f07-b386-5d08557e15c9/content/images/2021/04/image-73.png)

Nice try, sucka!

The compiler doesn't complain about using `1` as the key, since twinBASIC can implicitly coerce that into the String the CarLookup object expects. However, it is not able to coerce `"A"` into an oVehicle object, and it makes sure we know it.

### Avoiding subtle bugs with the added type safety

Using a fully-implemented version of this generic dictionary class in place of the anything-goes default version found in the scripting runtime can help us avoid subtle bugs like this one:

[The Subtle Dictionary Key BugAlways explicitly call the .Value property when using fields or controls as Dictionary keys. Else the bugs come crawling!![](https://nolongerset.com/favicon.png)No Longer SetMike Wolfe![](https://storage.ghost.io/c/eb/d7/ebd732c1-5f03-4f07-b386-5d08557e15c9/content/images/2020/12/key-5105878_1920.jpg)](https://nolongerset.com/the-subtle-dictionary-key-bug/)

In the above article, I detailed a bug that can appear if you use a textbox control as the key to a standard dictionary. As a developer, you may assume that the default .Value property of the control is being passed to the dictionary. But in fact, it's passing a reference to the textbox object itself and not the textbox's value. This goes back to the fact that the Key argument is a Variant, so literally anything you pass will be used as the key.

Here's the problematic code from that article:

```vba
Set EmployeePhoneNums = CreateObject("Scripting.Dictionary")
Me.tbLastName.Value = "Jones"
EmployeePhoneNums.Add Key:=Me.tbLastName, Item:="555-1234"
Me.tbLastName.Value = "Smith"
EmployeePhoneNums.Add Key:=Me.tbLastName, Item:="555-6789"
```

To avoid the bug completely, we could simply change the first line from...

```vba
Set EmployeePhoneNums = CreateObject("Scripting.Dictionary")
```

...to...

```vba
Set EmployeePhoneNums = New Dict(Of String, String)
```

Now, when the following line gets called...

```vba
EmployeePhoneNums.Add Key:=Me.tbLastName, Item:="555-1234"
```

...twinBASIC will see that the key *must be a String.* It will then *coerce* the textbox object (Me.tbLastName) into a String by fetching its default property, `.Value`, and using that as the key. Presto change-o, the bug is gone!

### Full example with semantic highlighting

Here's a screenshot of the full twinBASIC code with all that juicy semantic highlighting goodness:

![](https://storage.ghost.io/c/eb/d7/ebd732c1-5f03-4f07-b386-5d08557e15c9/content/images/2021/04/image-74.png)

*Image by [Francesco Romeo](https://pixabay.com/users/francisromeo-1845256/?utm%5Fsource=link-attribution&utm%5Fmedium=referral&utm%5Fcampaign=image&utm%5Fcontent=1665471) from [Pixabay](https://pixabay.com/?utm%5Fsource=link-attribution&utm%5Fmedium=referral&utm%5Fcampaign=image&utm%5Fcontent=1665471)*