说我有以下课程:
public class BaseClass {
...
}
public class ChildClass : BaseClass {
...
}
如果我想在方法调用中将ChildClass的单个实例作为类型BaseClass传递,我可以做到这一点。
public void SomeCall(BaseClass baseClass)
....
ChildClass childClass = new ChildClass();
SomeCall(childClass); <-- Works fine
但是,如果我想传入一个List,我似乎无法正确地投射它。
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和AutoMap列表中的每个对象到一个新的BaseClass列表。
答案 0 :(得分: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之下。)
答案 1 :(得分: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
方法将尝试将List
的每个元素转换为BaseClass
,如果任何强制转换失败,则会抛出,OfType
方法将过滤Enumerable
用于可以转换为BaseClass
的实例,并且仅返回这些实例。
你不能像{Eric}一样在this answer中回答,如果List
将其视为SomeCall
,则可以添加内容List<BaseClass>
它不是ChildClass
。你可以这样做:
List<ChildClass> childClasses = new List<ChildClass>();
SomeCall(childClasses.Cast<BaseClass>().ToList());
但这确实不是一个好主意,因为你要传递的实际上是一个新的List
实例。将SomeCall
的参数键入为List
而不是IEnumerable
的唯一原因是它需要修改列表,如果您将其传递Cast<BaseClass>().ToList()
,则它所做的改变将立即丢失。
如果您不打算对List
进行更改,则应将其作为IEnumerable
传递,并使用上述Linq方法动态投射。如果您打算进行更改,则应将列表转换为其他位置并存储,以便您可以访问这些更改。
答案 2 :(得分: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示例。
答案 3 :(得分: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()
;
...
}