20

我敢肯定,这个问题解决了在上一个问题中提出的问题,但我找不到它。

C# 类中有一个方法将基类的通用列表作为参数。我需要传递一个继承类的列表,但不知道该怎么做。我在尝试中遇到错误。下面是说明这一点的示例代码:

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

4 回答 4

31

如果你有可用的 linq,你可以做

var ListOfA = ListOfB.Cast<A>().ToList();
于 2009-03-26T15:38:58.767 回答
9

你不能这样做。要理解为什么不允许它,想象一下如果在 a被强制转换为 a 之后Add调用它会发生什么。List<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>直接将 a 传递给,MethodC而无需先对其进行奇怪的转换。所以没有不必要的复制。

之所以可行,是因为我们已经告诉我们MethodC要接受从 派生的任何内容的列表A,而不是坚持它必须是 的列表A

于 2009-03-26T15:41:14.287 回答
4

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

listOfB.Cast<A>();
于 2009-03-26T15:39:13.400 回答
3

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

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

OfType 方法将排除错误派生类的项目,因为 Cast 将引发错误。

于 2014-11-27T15:31:54.430 回答