Cast a generic List. C# and VB.NET

Cast a derived list to a base list gives a compile error:
Cannot implicitly convert type ‘System.Collections.Generic.List’ to ‘System.Collections.Generic.List’

Note that this example is a .NET3.5 example due to the lazy implementation of the property

    class Program
    {
        static void Main(string[] args)
        {
            List<MyDerivCls> derivCls = new List<MyDerivCls>();
            derivCls.Add(new MyDerivCls("Hello World1"));
            derivCls.Add(new MyDerivCls("Hello World2"));

            //Now I wan't to cast List<MyDerivCls> to List<IMyBase>, but that gives a compile error:
            //Cannot implicitly convert type 'System.Collections.Generic.List<ConsoleListDownCast.MyDerivCls>' to 'System.Collections.Generic.List<ConsoleListDownCast.IMyBase>'
            //List<IMyBase> baseList = derivCls;

            //Instead a helper function helps us out:
            List<IMyBase> baseList = MyDerivCls.ToListOfBase(derivCls);

            IMyBase baseObj = baseList[0];
            string myStr = baseObj.MyProperty;
            Console.WriteLine(myStr); //"Hello World1"
        }
    }

    interface IMyBase {
        string MyProperty { get; set; }
    }

    class MyDerivCls: IMyBase
    {
        public MyDerivCls(string InitValue) {
            MyProperty = InitValue;
        }

        public string MyProperty { get; set; }

        /// <summary>
        /// Just return the object unchanged, since it can be down casted to IMyBase directly
        /// </summary>
        ///
<param name="fromO"></param>
        /// <returns></returns>
        private static IMyBase ToBase(MyDerivCls fromO){
            return fromO;
        }

        /// <summary>
        /// You can cast MyClass to IMyCommon, but can't when they are in a list.
        /// That's why you must use a converter func
        /// </summary>
        ///
<param name="MyList"></param>
        /// <returns></returns>
        public static List<IMyBase> ToListOfBase(List<MyDerivCls> MyList) {
            Converter<MyDerivCls, IMyBase> listDownConverter = new Converter<MyDerivCls, IMyBase>(MyDerivCls.ToBase);
            //Cast the list using a converter function
            List<IMyBase> csvList1 = MyList.ConvertAll<IMyBase>(listDownConverter);
            return csvList1;
        }
    }

Note: The IMyBase interface could just as well have been a base class instead in this example.

And in VB.NET:

Module Module1
    Sub Main()
        Dim derivCls As New List(Of MyDerivCls)
        derivCls.Add(New MyDerivCls("Hello World1"))
        derivCls.Add(New MyDerivCls("Hello World2"))

        'Now I wan't to cast List<MyDerivCls> to List<IMyBase>, but that gives a compile error:
        'Cannot implicitly convert type 'System.Collections.Generic.List<ConsoleListDownCast.MyDerivCls>' to 'System.Collections.Generic.List<ConsoleListDownCast.IMyBase>'
        'Dim baseList As List(Of IMyBase) = derivCls

        'Instead a helper function helps us out:
        Dim baseList As List(Of IMyBase) = MyDerivCls.ToListOfBase(derivCls)

        Dim baseObj As IMyBase = baseList(0)
        Dim myStr As String = baseObj.MyProperty
        Console.WriteLine(myStr) '"Hello World1"
    End Sub
End Module

Public Interface IMyBase
    Property MyProperty() As String
End Interface

Public Class MyDerivCls
    Implements IMyBase

    Public Sub New(ByVal InitValue As String)
        MyProperty = InitValue
    End Sub

    Private _myProperty As String
    Public Property MyProperty() As String Implements IMyBase.MyProperty
        Get
            Return _myProperty
        End Get
        Set(ByVal value As String)
            _myProperty = value
        End Set
    End Property

    ''' <summary>
    ''' Just return the object unchanged, since it can be down casted to IMyBase directly
    ''' </summary>
    '''
<param name="fromO"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Private Shared Function ToBase(ByVal fromO As MyDerivCls) As IMyBase
        Return fromO
    End Function

    ''' <summary>
    ''' You can cast MyClass to IMyCommon, but can't when they are in a list.
    ''' That's why you must use a converter func
    ''' </summary>
    '''
<param name="MyList"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Shared Function ToListOfBase(ByRef MyList As List(Of MyDerivCls)) As List(Of IMyBase)
        Dim listDownConverter As New Converter(Of MyDerivCls, IMyBase)(AddressOf MyDerivCls.ToBase)
        'Cast the list using a converter function
        Dim myList1 As List(Of IMyBase) = MyList.ConvertAll(Of IMyBase)(listDownConverter)
        Return myList1
    End Function
End Class
Advertisements

Leave a Reply

Please log in using one of these methods to post your comment:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: