当Class B继承自ClassA时,如何将List <class>强制转换为List <class>?</classa> </classb>

时间:2011-10-31 15:33:21

标签: c# c#-4.0 casting

我将json字符串反序列化为List<ClassB>,现在我想将其转换为List<ClassA>,然后再将其返回  BindModel方法。我需要进行转换,因为方法需要获得List<ClassA>

为什么我在投票时会收到错误?毕竟,ClassB继承自ClassA。我该怎么办?

P.S。这个问题从this post延伸出来。在行new DataContractJsonSerializer(typeof(List<ClassB>));而不是List<ClassB>中,类型将在运行时构建。

    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; }
    }

5 个答案:

答案 0 :(得分:10)

您可以使用

 Cast<T>()

例如:

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

这实际上低于Linq ,并且在IEnumerable而不是IEnumerable<T>上实施,但仍然有用。它是效率不高,因为正如我所说,它试图施展它。

记住列表不允许协方差,这是一种麻烦。最好使用IEnumerable<T>作为接口而不是List。

你可以说:

 IEnumerable<B> listOfB = new List<B>();
 IEnumerable<A> listOfA = listOfB; // no casting required

答案 1 :(得分:6)

您可以使用Cast Method

return list.Cast<ClassB>();

查看有关Co和Contra Variance的this question

答案 2 :(得分:2)

我会像这样投射名单:

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

这对你有用吗?

答案 3 :(得分:1)

您无法将 SubType 的列表强制转换为 SuperType 列表。假设我有一个Tortoises列表,我可以把它放到一个动物列表中。然后我可以在狮子列表中加一只狮子,但狮子的类型不正确。

使用枚举,你可以这样做。之前的海报非常正确地说您可以将 SubType 的列表强制转换为 SuperType 的IEnumerable。实际上,在C#4中,IEnumerable SubType SuperType 的IEnumerable。这是因为泛型参数被指定为out参数。

答案 4 :(得分:1)

要从List<BaseClass>创建List<DerivedClass>,演员阵容是不够的,正如其他答案所指出的那样。您需要构建一个新列表。

我对其他答案建议的代码并不是特别满意,所以我提供了自己的解决方案。我会这样做:

var baseClassList = new List<BaseClass>(derivedClassList.Cast<BaseClass>());

有些人可能更喜欢这个:

var baseClassList = derivedClassList.Cast<BaseClass>().ToList();

我更喜欢第一个,因为它可以很容易地将类型从List<T>更改为使用带有IEnumerable<T>的构造函数的任何其他集合。