将基类型列表转换为inheritance类型列表
我确信这个问题可以解决上一个问题中提出的问题,但我无法找到它。
C#类中有一个方法,它将基类的通用List作为参数。 我需要传递一个inheritance类的列表,并且不确切知道如何执行此操作。 我的尝试中出现错误。 以下是示例代码:
public class A { public static void MethodC(List) { // 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 listOfB = new List(); A.MethodC( (List) listOfB ); // Error: this does not work A.MethodC( listOfB.ToList() ); // Error: this does not work A.MethodC( listOfB.ConvertAll(typeof(A)) ); // Error: this does not work // how can I accomplish this? It should be possible I would think
注意:这是我的最终工作方法作为参考。 我对我的问题得到了更好的解决方案,但从技术上讲,这不是问题的答案,因为我的问题是不正确的。
public static DataTable ObjectCollectionToDataTable (List 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; }
如果你有linq可用,你可以做到
var ListOfA = ListOfB.Cast().ToList();
你不能这样做。 要理解为什么不允许这样做,想象一下如果在将List
转换为List
之后调用Add
,会发生什么。
此外,暗示C#4.0将不同的答案是错误的。 永远不会修改列表以允许您执行此操作。 只有IEnumerable
会 – 因为它不允许将项目添加到集合中。
更新:它在你所使用的解决方案中工作的原因是因为你不再传递相同的列表。 您正在创建一个全新的列表,它是原始列表的副本。 这就是我询问修改列表的原因; 如果MethodC
更改了列表中的项目数,则会对副本进行更改,而不是原始列表。
我认为理想的解决方案如下:
public abstract class A { public void MethodC(List 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 listOfB = new List(); A a = new B(); a.MethodC(listOfB); } }
请注意,使用此解决方案,您可以将List
直接传递给MethodC
而无需先对其进行奇怪的转换。 所以没有必要的复制。
这样做的原因是因为我们告诉MethodC
接受从A
派生的任何事物的列表,而不是坚持它必须是A
的列表。
您正在解决当前C#版本中缺乏协方差的问题。 这是一种方法:
listOfB.Cast();
这是一个答案,将排除错误类型列表中的任何对象。 在我看来,这是一种更安全的方式:
List ListOfA = ListOfB.OfType().ToList();
OfType方法将排除错误的派生类的项目,因为Cast将抛出错误。