Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to cast List<ClassB> to List<ClassA> when ClassB inherits from ClassA?

Tags:

c#

casting

c#-4.0

I deserialized json string to List<ClassB> and now I want to cast it to List<ClassA> before I return it from BindModel method. I need casting because the methods expects to get List<ClassA>.

Why I get error while casting? After all, ClassB inherits from ClassA. What should I do?

P.S. this question is extended from this post. In line new DataContractJsonSerializer(typeof(List<ClassB>)); instead of List<ClassB> the type will be constructed at runtime.

    public override object BindModel(...)
    {
          var serializer = new DataContractJsonSerializer(typeof(List<ClassB>));
          MemoryStream ms = new MemoryStream(Encoding.UTF8.GetBytes("[{\"id\":\"1\",\"name\":\"name\"}]"));
          var list = serializer.ReadObject(ms);

          return (List<ClassA>)list;
    }

    [KnownType(typeof(ClassA))]
    [DataContract]
    public class ClassA
    {
        public ClassA();
    }

    [KnownType(typeof(ClassB))]       
    [DataContract]
    public class ClassB : ClassA
    {
        [DataMember(Name = "id")]
        public int Id { get; set; }
        [DataMember(Name = "name")]
        public string CategoryName { get; set; }
    }
like image 660
theateist Avatar asked Oct 31 '11 15:10

theateist


4 Answers

You can use

 Cast<T>()

For example:

 List<A> listOfA = new List<B>().Cast<A>();

This in fact is inferior to Linq and is implemented on IEnumerable rather than IEnumerable<T> but still is useful. It is not efficient since as I said, it tries to cast it.

Remember List does not allow for covariance which is a nuisance. It is preferable to use IEnumerable<T> as interface rather than List.

You can say:

 IEnumerable<B> listOfB = new List<B>();
 IEnumerable<A> listOfA = listOfB; // no casting required
like image 98
Aliostad Avatar answered Sep 26 '22 03:09

Aliostad


You can use the Cast Method.

return list.Cast<ClassB>();

Have a look at this question about Co and Contra Variance

like image 44
Ray Avatar answered Sep 26 '22 03:09

Ray


I would cast the lists like this:

var listB = GetListOfB();  // returns List<B>
var listA = listB.Select(q => (A)q).ToList();

Will that work for you?

like image 45
Glenn Ferrie Avatar answered Sep 27 '22 03:09

Glenn Ferrie


You can't cast a List of SubType to a List of SuperType. Suppose I have a list of Tortoises, and I was able to cast it to a list of Animals. Then I could add a lion, to a list of Tortoises, but a Lion isn't of the correct type.

With enumerables, you can do this, however. The previous posters are quite correct in saying that you can cast a List of SubType to an IEnumerable of SuperType. In fact, in C# 4, and IEnumerable SubType is an IEnumerable of SuperType. This is because the generic parameter is specified as an out parameter.

like image 30
Adam Brown Avatar answered Sep 26 '22 03:09

Adam Brown