我最近遇到的情况是,当我期待List<Base>
时,我收到了List<Derived>
,这正是我所需要的。事实证明,Derived是Base的子类,而List<Base>
实际上包含了我需要的Derived对象。
但是,我收到的List是从第三方API返回的,我现在担心它最终可能会返回多个派生自Base的类型。我需要将List<Base>
转换为List<Derived>
,我想确保我只是转换我需要的类型,同时安全地跳过与我需要的那些无关的任何其他子类型。 / p>
例如,如果我有以下类层次结构:
public class Derived : Base {}
public class DerivedOne : Base {}
public class Base {public int i;}
然后我从以下代码得到以下结果:
static void Main(string[] args)
{
List<Base> bList = new List<Base>() {new Derived(), new DerivedOne()};
List<Derived> dList = new List<Derived>();
/*InvalidCastException*/
// dList = bList.ConvertAll(x => (Derived)x);
/*InvalidCastException*/
// dList = new List<Derived>(bList.Cast<Derived>());
/*Works, but essentially 'converts' DerivedOne object
to Derived object, which would be unwanted.*/
dList = bList.ConvertAll(x => new Derived{i = x.i});
// or
dList = bList.Select(x => new Derived{i = x.i}).ToList();
/* Works, but is there a cleaner way using LINQ? */
dList = new List<Derived>();
foreach(Base b in bList) {
Derived d = b as Derived;
if (d != null)
dList.Add(d);
}
}
所以,我的问题是:如何使用LINQ从List<Derived>
创建List<Base>
而不抛出InvalidCastException或从不相关的DerivedOne类创建Derived对象?
答案 0 :(得分:4)
你可以使用
dList.Where(i=> i is Derived).ToList().ConvertAll(i => (Derived)i);
或
dList.OfType<Derived>().ToList()
答案 1 :(得分:0)
Ga berber,
杨磊说这是最好的答案。在框架的可维护性和可重用性方面,最好的解决方案是LINQ的OfType方法。它作为IEnumerable的扩展存在,是System.Linq命名空间的一部分。以下是资源链接:https://msdn.microsoft.com/en-us/library/bb360913%28v=vs.110%29.aspx?f=255&MSPPError=-2147217396
以下是您上面的代码:
static void Main(string[] args)
{
List<Base> bList = new List<Base>() {new Derived(), new DerivedOne()};
List<Derived> dList = bList.OfType<Derived>().ToList();
}
答案 2 :(得分:0)
要仅从Derived
项序列中提取Base
个项目,请使用Enumerable.OfType。
不同类型的序列: IEnumerable someBaseTypes = ... IEnumerable someDerivedTypes = ... IEnumerable someOtherDerivedTypes = ...
混合它们。你不再是他们的类型了:
IEnumerable<Base> mixedCollection = someBaseTypes
.Concat(someDerivedTypes.Cast<Base>())
.Concat(someOtherDerivedTypes.Cast<Base>());
仅获取派生的。使用OfType
IEnumerable onlyDerivedTypes = mixedCollection .OfType();
请注意,如果该集合还包含Derived的子类,那么您的结果中也会包含它们