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

发布于 2024-07-16 01:59:46 字数 1462 浏览 7 评论 0原文

我确信这个问题解决了上一个问题中提出的问题,但我找不到它。

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

I would be certain that this question addresses something that would have been brought up in a previous question, but I was unable to find it.

There is a method in a C# class that takes as a parameter a generic List of a Base Class. I need to pass a list of an inherited class and do not know exactly how to do this. I am getting an error in my attempts. Below is sample code to illustrated this:

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

Note: Here is my final working Method as a reference. I got an even better solution to my problem, but technically it wasn't an answer to the question, since my question was phrased impropertly.

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

埖埖迣鎅 2024-07-23 01:59:46

如果你有 linq 可用,你可以这样做

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

If you have linq available you can do

var ListOfA = ListOfB.Cast<A>().ToList();
太阳哥哥 2024-07-23 01:59:46

你不能这样做。 要理解为什么不允许这样做,想象一下如果在将 List 转换为 List后在 List 上调用 Add 会发生什么。

此外,暗示 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 直接传递给 MethodC 而无需进行那种奇怪的转换首先。 所以没有不必要的复制。

之所以有效,是因为我们告诉 MethodC 接受从 A 派生的任何内容的列表,而不是坚持它必须是 的列表一个。

You cannot do that. To understand why it is not allowed, imagine what would happen if Add was called on a List<Derived> after it had been cast to a List<Base>.

Also, the answers implying that C# 4.0 will be different are wrong. List will never be modified to allow you to do this. Only IEnumerable will - because it does not allow items to be added to the collection.

Update: The reason it works in the solution you've gone for is because you're no longer passing the same list. You're creating a whole new list which is a copy of the original. This is why I asked about modifying the list; if MethodC makes changes to the number of items on the list, those changes would be made to a copy, not the original list.

I think the ideal solution for you is as follows:

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

Notice how, with this solution, you can pass a List<B> directly to MethodC without needing to do that weird conversion on it first. So no unnecessary copying.

The reason this works is because we've told MethodC to accept a list of anything that is derived from A, instead of insisting that it must be a list of A.

彻夜缠绵 2024-07-23 01:59:46

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

listOfB.Cast<A>();

You are addressing the lack of covariance in the current C# version. Here is one way of doing it:

listOfB.Cast<A>();
夜清冷一曲。 2024-07-23 01:59:46

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

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

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

Here is an answer that will exclude any objects in your list of the wrong type. This is a much safer way in my opinion:

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

The OfType method will exclude items of the wrong derived class where as the Cast will throw an error.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文