Search code examples
c#genericssdk

Convert SDKList to List<T>


I do have a class from a SDK which acts as an list. Its name is SDKList. SDKList has a member Item, which contains several SDK specific Types (e.g. SDKElement, SDKSurface, SDKBody) There is also a member Type which specifies wheather the Items are SDKElement, SDKSurface or SDKBody.

What i want is a generic method to convert the SDKList in a C# List.

Sofar I have a non generic method for the Item type SDKElement:

public static List<SDKElement> sdkListToCSharpList(SDKList sdkList)
        {
            if (sdkList.ItemType != (short)VListTypes.LTYPE_ELEM) return null;
            List<SDKElement> result = new List<SDKElement>();
            for (int i = 1; i <= sdkList.Count; i++)
            {
                SDKElement elm = sdkList.Item(i);
                result.Add(elm);
            }
            return result;
        }

What I want is something like this:

public static List<T> sdkListToCSharpList(SDKList sdkList)
{
...
}

How does the method need to be changed to work generic and process all kinds of Item Types? Since i haven't worked worked much with gneric I don't understand how to make it generic since SDKList is a single Type and contains the acutual generic Items.

Thank you in advance.


Solution

  • What I want is something like this: public static List<T> sdkListToCSharpList(SDKList sdkList)

    You cannot. According to your description the type of the objects in the list may vary in runtime. Generics is a compile time concept, so you cannot make a generic type vary at runtime, at least not without reflection.

    What you can do is declare the type you expect the list to have, i.e.

    public static List<T> sdkListToCSharpList<T>(SDKList sdkList)
    

    But you will need some way to handle cases where the runtime type does not match your compile time, generic, type. This might be to return an empty list, throw an exception, or some other way to signal the error.

    I would personally use LINQ to create an iterator for the list:

    public static IEnumerable<T> ToEnumerable<T>(this SDKList sdkList){
        var runtimeType = sdkList.ItemType  switch{
               VListTypes.LTYPE_ELEM => typeof(SDKElement)
               VListTypes.LTYPE_SURF => typeof(SDKSurface )
               ...
               _ => throw new InvalidOperationException(...)
        };
        if(runtimeType != typeof(T)){
             throw new InvalidOperationException(...);
        }
        for (int i = 1; i <= sdkList.Count; i++){ // one based indexing? really?
            yield return (T)sdkList.Item(i);
        }
    }
    

    And call it like:

    var sdkElementList = mySdkList.ToEnumerable<SDKElement>().ToList();
    

    That way you will get a runtime exception if your actual runtime type does not match the type you expect in runtime. If you instead want an empty list you could remove all the type-checks, return a IEnumerable<object> and use .OfType<T>() to only get the objects where the runtime type matches the expected type.