将基类型列表转换为继承类型列表

时间:2009-03-26 15:36:39

标签: c# generic-list

我确信这个问题可以解决上一个问题中提出的问题,但我无法找到它。

C#类中有一个方法,它将参数作为基类的通用List。我需要传递一个继承类的列表,并且不知道如何执行此操作。我的尝试中出错了。以下是示例代码:

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

注意:这是我的最终工作方法作为参考。我对我的问题得到了更好的解决方案,但从技术上讲,这不是问题的答案,因为我的问题是不正确的。

 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;
        }

4 个答案:

答案 0 :(得分:30)

如果你有linq,你可以做

var ListOfA = ListOfB.Cast<A>().ToList();

答案 1 :(得分:9)

你做不到。要理解为什么不允许这样做,想象一下如果AddList<Derived>被投放到List<Base>之后被调用会发生什么。

此外,暗示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);
    }
}

请注意,使用此解决方案,您可以直接将List<B>传递给MethodC,而无需先对其进行奇怪的转换。所以没有不必要的复制。

这样做的原因是因为我们告诉MethodC接受从A派生的任何内容的列表,而不是坚持它必须是A的列表。

答案 2 :(得分:4)

您正在解决当前C#版本中缺乏协方差问题。这是一种方法:

listOfB.Cast<A>();

答案 3 :(得分:3)

这是一个答案,它会排除错误类型列表中的所有对象。在我看来,这是一种更安全的方式:

List<A> ListOfA  = ListOfB.OfType<A>().ToList();

OfType方法将排除错误的派生类的项目,因为Cast会抛出错误。