2

I'm trying to write an adapter class that accepts any Dictionary/KeyValuePair-ish type as a parameter.

Public Class Adapter(Of TKey As IComparable, TValue, TContainer As {IDictionary, New})
    Private Structure Entry
        Public Value as TValue
        ' Some other stuff
    End Property

    Private _Container As TContainer(Of TKey, Entry) ' <-- how do I make TContainer still parametrizable

    Public Sub New()
        _Container = New TContainer(Of TKey, Entry) ' <-- TContainer needs to be New-able
    End Sub
End Class

Does VB.NET allow this type of nested generic parameter (like template template parameters in C++)? and if so, how do I write the generic parameters to accept one?

Expected Usage

Ideally, I'd want to be able to use it like this:

Dim adapter As Adapter(Of String, String, Dictionary) ' <-- _Container will then be Dictionary(String, Entry(Of String))

Additionally

Additionally, is there a way to implement a constructor that accepts an object of type TContainer(Of TKey, Entry).

Public Sub New(ByVal container As TContainer(Of TKey, Entry)) '<-- use existing container
    _Container = container
End Sub

The only way I see this happening is by making Entry public but then I'd have to do something like Adapter(Of String, String, Adapter(WHAT_DO_I_PUT_HERE).Entry. How can I refer to the inner Entry class if I can't complete the generic Adapter signature?

  • I assume you're already aware of `Adapter(Of TKey As IComparable, TValue, TContainer As {IDictionary(Of TKey, TValue), New})` and `Dim adapter As Adapter(Of String, String, Dictionary(Of String, String))`, but want to remove the redundant `(Of String, String)`? – GSerg Mar 03 '19 at 12:40
  • @GSerg My problem is that internal `Entry` class, if I define `TContainer` as `TContainer As {IDictionary(Of TKey, TValue), New}` I can no longer do `Private _Container As TContainer(Of TKey, Entry)` because `TContainer` is no longer parametrizable. I think I'm basically asking if *template template parameters* (from C++) exists in .NET land (not too familiar with Generics terminology). – John Mark Gabriel Caguicla Mar 03 '19 at 12:59
  • I don't think you can do that, at least not without exposing the `Entry` class. But in order to expose `Entry`, you will need to move it out of `Adapter`, otherwise there will be no way to refer to its type from outside, as for that you first would need to spell out the generic arguments of `Adapter`, and `Entry` will be one of them, which is a circular dependency. Do you really have to provide a concrete type for the `IDictionary`? It would appear you would be just fine always creating a `Dictionary` inside `Adapter`. – GSerg Mar 03 '19 at 16:17
  • It is difficult to see why you need to specify TContainer as a generic type argument. Does this class expose `_Container`? As stated by @GSerg, you need to make the `Entry` type accessible outside of the class; you could possibly make it implement an accessible interface type and use that interface as a generic constraint. – TnTinMn Mar 03 '19 at 18:47
  • @TnTinMn The only reason I could think of is that there are custom generic storage classes with side effects, and the caller wants to make sure `Adapter` instantiates a specific type of storage for its side effects, even though `Adapter` itself will only see the `IDictionary` side of it. Without exposing `Entry`, I believe it can only be done by passing the desired type's name as a string to the `Adapter`'s constructor and then [instantiating the generic type manually](https://stackoverflow.com/a/7450975/11683), but then I'm not sure if VB has a way to express the `typeof(MyClass<>)`. – GSerg Mar 03 '19 at 19:35

0 Answers0