How to get the type of a non generic IList

I have a situation (Deserializer) where I have the System.Type of something that I know inherits from IList. From this method, I need to give back an instance of this type and make sure it has x elements, all filled with the default value.

Simplified code:

Public Function GetIListInstance(theType as System.Type) as IList
    ...
End Function

When the IList is a simple array, the solution is also simple; the type name ends with []
Making the code:

Public Function GetIListInstance(theType as System.Type) as IList
    If theType.Name.EndsWith("[]") Then
      Return theType.InstantiateArray(3) //return an array with 3 empty elements
    Else
      //not an array
      ...
    End If
End Function

When the IList is something else, I can make an instance of it, and use the IList interface to add the 3 elements:

Public Function GetIListInstance(theType as System.Type) as IList
    If theType.Name.EndsWith("[]") Then
      Return theType.InstantiateArray(3) //return an array with 3 empty elements
    Else
      //not an array,  code for .Net: Activator.CreateInstance
      Dim MyList = TheType.Instantiate 
      For i = 1 to 3
        DirectCast(MyList, IList).Add(...)
      Next
      Return MyList
    End If
End Function

Then, I only need to know what the type of the elements of this IList is.
When the list isn’t empty, this would be simple. But in this case, as we just created the list, it IS empty.

In .Net, I can get a copy of the underlaying array of the IList (which will be an empty array), and get the type of this array:

Dim UnderlayingArrayType =  DirectCast(MyList, Dynamic).ToArray.GetType

And then I can create a new array with 1 uninitialized element; the value of this element is the default value that I need:

Dim DefaultValue = DirectCast(UnderlayingArrayType.InstantiateArray(1), IList).Item(0)

So the complete code becomes:

Public Function GetIListInstance(theType as System.Type) as IList
    If theType.Name.EndsWith("[]") Then
      Return theType.InstantiateArray(3) //return an array with 3 empty elements
    Else
      //not an array,  code for .Net: Activator.CreateInstance
      Dim MyList = TheType.Instantiate 
      //get the type of the underlaying array
      Dim UnderlayingArrayType =  DirectCast(MyList, Dynamic).ToArray.GetType
      //get a default value for this array
      Dim DefaultValue = DirectCast(UnderlayingArrayType.InstantiateArray(1), IList).Item(0)
      For i = 1 to 3
        DirectCast(MyList, IList).Add(DefaultValue)
      Next
      Return MyList
    End If
End Function

So far, so good - this works when compiled to .Net

The problem
ToArray does not exist when I compile to Island, so the code to get the default value doesn’t work here.

The question
How do I get the default value for an item of an IList when compiling for Island?

So you need something like the generic IList (which all collections implement really) to be able to get the argument type and get the sub type (ie Array of Integer already implements IList) that’s 1.

i figure you want it boxed as an Object.
For non valuetypes, it’s easy, just nul.

I don’t think we have an api for structs yet, but it’s something like:

var aType: &Type;
        var lRes := DefaultGC.New(aType.RTTI, aType.SizeOfType + aType.BoxedDataOffset);
   exit InternalCalls.Cast<Object>(lRes)

That gives “Not supported” as error in Wasm …

Doesn’t mean we can’t solve this.

I think the code should work for a List(Of something).

As List(Of Something) implements IList - bit also implements IList(Of T), it should be able to dynamically invoke the ToArray method from that interface.

Stays the problem that an Array can’t be recognized as such and even when you can, it can’t be instantiated by the InstantiateArray method when using WASM.

recognized from what? the Reflection.Type obtained from the array instance at runtime? seems if that’s a gap in Reflection, it should be possible to add support for that.

You shod just be able to call type.CreateArray(), and then create instances and shove them into each spot, no?

No, just from the system.type - no reflection used here

1 Like

@mh I think we should just log this to implement this better. Either way a nice API would help a lot here.

yeah.

Logged as bugs://E25210.