C# 将基类型的列表转换为继承类型的列表
我可以肯定,这个问题涉及到了在前面的问题中可能会提出的一些问题,但我找不到它 C#类中有一个方法,它将基类的泛型列表作为参数。我需要传递一个继承类的列表,但我不知道该怎么做。我在尝试中出错了。下面是示例代码来说明这一点:C# 将基类型的列表转换为继承类型的列表,c#,generic-list,C#,Generic List,我可以肯定,这个问题涉及到了在前面的问题中可能会提出的一些问题,但我找不到它 C#类中有一个方法,它将基类的泛型列表作为参数。我需要传递一个继承类的列表,但我不知道该怎么做。我在尝试中出错了。下面是示例代码来说明这一点: public class A { public static void MethodC(List<A>) { // Do Something here with the list } } public Class B : A {
public class A
{
public static void MethodC(List<A>)
{
// Do Something here with the list
}
}
public Class B : A
{
// B inherits from A, A is the Base Class
}
// Code utilizing the above method
List<B> listOfB = new List<B>();
A.MethodC( (List<A>) listOfB ); // Error: this does not work
A.MethodC( listOfB.ToList<typeof(A)>() ); // Error: this does not work
A.MethodC( listOfB.ConvertAll<A>(typeof(A)) ); // Error: this does not work
// how can I accomplish this? It should be possible I would think
公共A类
{
公共静态无效方法C(列表)
{
//在这里用列表做些什么
}
}
B级:A级
{
//B继承自A,A是基类
}
//使用上述方法的代码
List listOfB=新列表();
A.MethodC((列表)listOfB);//错误:这不起作用
A.MethodC(listOfB.ToList());//错误:这不起作用
A.MethodC(listOfB.ConvertAll(typeof(A));//错误:这不起作用
//我怎样才能做到这一点?我认为这应该是可能的
注:以下是我的最终工作方法,仅供参考。我找到了一个更好的解决问题的办法,但从技术上讲,这并不是问题的答案,因为我的问题措辞不当
public static DataTable
ObjectCollectionToDataTable<GLIST>
(List<GLIST> ObjectCollection) where GLIST
: BaseBusinessObject
{
DataTable ret = null;
if (ObjectCollection != null)
{
foreach ( var b in ObjectCollection)
{
DataTable dt = b.ToDataTable();
if (ret == null)
ret = dt.Clone();
if (dt.Rows.Count > 0)
ret.Rows.Add(dt.Rows[0].ItemArray);
}
}
return ret;
}
公共静态数据表
ObjectCollectionToDataTable
(列出ObjectCollection)其中
:BaseBusinessObject
{
DataTable ret=null;
if(ObjectCollection!=null)
{
foreach(ObjectCollection中的变量b)
{
DataTable dt=b.ToDataTable();
if(ret==null)
ret=dt.Clone();
如果(dt.Rows.Count>0)
ret.Rows.Add(dt.Rows[0].ItemArray);
}
}
返回ret;
}
如果您有linq可用,您可以
var ListOfA = ListOfB.Cast<A>().ToList();
var ListOfA=ListOfB.Cast().ToList();
您正在解决当前C#版本中缺少协方差的问题。以下是一种方法:
listOfB.Cast<A>();
listOfB.Cast();
您不能这样做。要理解为什么不允许这样做,请想象一下,如果在将列表转换为列表
后,对列表
调用了添加
,会发生什么情况
此外,暗示C#4.0将有所不同的答案是错误的。列表将永远不会被修改以允许您执行此操作。只有IEnumerable
会-因为它不允许将项目添加到集合中
更新:它在您选择的解决方案中起作用的原因是您不再传递相同的列表。您正在创建一个全新的列表,它是原始列表的副本。这就是为什么我要修改列表;如果MethodC
对列表中的项目数进行更改,则这些更改将被复制到副本中,而不是原始列表中
我认为理想的解决方案如下:
public abstract class A
{
public void MethodC<TItem>(List<TItem> list) where TItem : A
{
foreach (var item in list)
item.CanBeCalled();
}
public abstract void CanBeCalled();
}
public class B : A
{
public override void CanBeCalled()
{
Console.WriteLine("Calling into B");
}
}
class Program
{
static void Main(string[] args)
{
List<B> listOfB = new List<B>();
A a = new B();
a.MethodC(listOfB);
}
}
公共抽象类A
{
公共无效方法c(列表),其中TItem:A
{
foreach(列表中的变量项)
item.CanBeCalled();
}
公共摘要无效可以称为();
}
B级:A级
{
公共覆盖无效可以调用()
{
控制台写入线(“呼叫B”);
}
}
班级计划
{
静态void Main(字符串[]参数)
{
List listOfB=新列表();
A=新的B();
a、 方法c(列表b);
}
}
请注意,使用此解决方案,您可以将列表
直接传递给MethodC
,而无需首先对其进行奇怪的转换。因此,没有不必要的复制
之所以这样做,是因为我们告诉MethodC
接受从a
派生的任何对象的列表,而不是坚持它必须是a
的列表。下面的答案将排除列表中任何类型错误的对象。在我看来,这是一种更安全的方式:
List<A> ListOfA = ListOfB.OfType<A>().ToList();
List ListOfA=ListOfB.OfType().ToList();
OfType方法将排除错误派生类的项,因为强制转换将抛出错误。我认为我没有linq,但它仍然有效。非常感谢您的快速回复。可能的问题-MethodC是否需要修改列表,以便在MethodC之外可以看到这些更改?很高兴它成功了!我认为您可以使用LINQ扩展方法的唯一原因是您的示例中使用了ToList。现在,它不需要修改列表,它将遍历集合并对每个集合调用抽象方法。您可以跳过“.Cast”:var ListOfA=ListOfB.ToList();这只提供一个IEnumerable,而不是List。这是因为((List)listOfB.Cast())在我显式将其转换为List时提供了我想要的内容。我不认为这是真的,它可以正常工作。我的方法调用在集合中循环并作用于抽象(重写)方法和属性。我在前面的回复中使用了上面的代码,效果非常好。该项目是.NET 2.0,使用CSC.exe(C#)3.0作为编译器。我猜您在运行该项目时遇到了困难?:)这和我给你的答案是一样的……从技术上讲,这也是你最初问的问题的答案!:)