2

假设我有以下课程:

public class BaseClass {
    ...
}

public class ChildClass : BaseClass {
    ...
}

如果我想在方法调用中将 ChildClass 的单个实例作为 BaseClass 类型传递,我可以这样做。

public void SomeCall(BaseClass baseClass)

....

ChildClass childClass = new ChildClass();
SomeCall(childClass);  <-- Works fine

但是,如果我想传入一个列表,我似乎无法正确地转换它。

public void SomeCall(List<BaseClass> baseClasses) 

....

List<ChildClass> childClasses = new List<ChildClass>();
SomeCall(childClasses);  <--  Gets compiler error

我得到的错误是

Argument 1: cannot convert from 'System.Collections.Generic.List<ChildClass>'
  to 'System.Collections.Generic.List<BaseClass>'

有没有办法将列表中的值转换为基类的类型?

现在,我想我只需要使用 foreach 并将列表中的每个对象自动映射到 BaseClass 的新列表。

4

4 回答 4

2

您最好的选择是在这里使用泛型,例如:

public void SomeCall<T>(List<T> list) where T: BaseClass
{
   foreach(T item in list)
   {
       // Assumes BaseClass defines method doSomething
       item.doSomething(....);
   }
}

调用方法做

SomeCall<ChildClass>(listOfChildren);

其他选择:

您可以只声明您的列表,以便它实际上与List<BaseClass>. 例如,

// Assumes Children extends BaseClass
List<BaseClass> list = new List<Children>();

考虑到您的应用程序,这可能会也可能不会,但如果您从未使用过泛型或无法使用泛型,这会更容易(不确定第一部分中的语法在 .NET 4.0 下是否有效。)

于 2013-09-27T00:08:20.710 回答
2

首先,您的方法是否有任何理由public void SomeCall(List<BaseClass> baseClasses)代替public void SomeCall(IEnumerable<BaseClass> baseClasses)?除非您特别需要它作为List<BaseClass>,比如要向其中添加内容,否则您应该将其作为 传递IEnumerable<BaseClass>,因为这将使您可以灵活地执行以下任一操作:

List<ChildClass> childClasses = new List<ChildClass>();
SomeCall(childClasses.Cast<BaseClass>());

或者:

List<ChildClass> childClasses = new List<ChildClass>();
SomeCall(childClasses.OfType<BaseClass>());

Cast方法将尝试将 in 的每个元素强制List转换BaseClass,并在任何强制转换失败时抛出,而该OfType方法将过滤Enumerable可强制转换的 for 实例BaseClass并仅返回这些实例。

您不能那样投List,因为正如 Eric Lippert 在此答案中回答的那样,如果SomeCall将其视为 a List<BaseClass>,那么它可以向其中添加不是 的东西ChildClass。你可以这样做:

List<ChildClass> childClasses = new List<ChildClass>();
SomeCall(childClasses.Cast<BaseClass>().ToList());

但这确实不是一个好主意,因为您将传递的实际上是一个新List实例。SomeCall将's 参数键入为 aList而不是的唯一原因IEnumerable是它需要修改列表,如果你传递它Cast<BaseClass>().ToList(),那么它所做的更改将立即丢​​失。

如果您不打算对 进行更改List,则应将其作为 an 传递IEnumerable并使用上述 Linq 方法动态转换。如果您确实打算进行更改,则应将列表转换到其他位置并将其存储,以便您可以访问这些更改。

于 2013-09-27T01:09:33.090 回答
0

如果您的源列表可能包含列表包含的超类型的不同子类型,您可以使用 Linq 执行以下操作:

class SuperType
{
  ...        
}
class SubType : SuperType
{
  ... 
}

static void DoSomethingInteresting( List<SuperType list )
{
  List<SubType> desired = list.Select( x => x as SubType )
                              .Where( x => x != null )
                              .ToList()
                              ;
  ...
}
于 2013-09-27T00:47:02.813 回答
0
public interface IBaseClass
{

}
public class BaseClass : IBaseClass
{

}

public class ChildClass : BaseClass, IBaseClass {

}

public void SomeCall(IBaseClass BassClass)
{
    BassClass.Dump();
}

public void SomeCall(List<IBaseClass> BassClasses)
{
    BassClasses.Dump();
}
void Main()
{
    List<IBaseClass> _ch = new List<IBaseClass>();
    _ch.Add(new ChildClass());
    _ch.Add(new ChildClass());
    _ch.Add(new ChildClass());

    SomeCall(_ch);
}

// Define other methods and classes here

接口;这是一个 LinqPad 示例。

于 2013-09-27T00:14:24.697 回答