不使用LINQ将对象列表转换

3

以下是我在这里提出的问题:Cast in List object

我接受了使用LINQ的答案:

myA = myB.Cast<A>().ToList();

我有一个问题:除了使用LINQ,我们是否有其他解决方案,因为我的应用程序正在使用.NET Framework 2.0。
更新: 如果我有几个类myB、myC、myD、myE等都是从myA派生而来的,我需要一个函数来将列表转换为列表(T可能是myB、myC、myD等),以避免重复相同的代码。函数的输入是一个列表<T>,输出是一个列表<myA>。
谢谢。

你可以编写自己的版本,循环遍历、转换类型并收集到一个类型化的集合中。 - Gishu
3个回答

5

一个简单的 foreach 就可以解决问题(为了阅读性,我给类命名为 Foo 和 Bar)

myFoos = new List<Foo>();
foreach (Bar bar in myBars)
{
  myFoos.Add((Foo)bar);
}

修改问题后:

要将多个子类的列表转换为基类,我会创建一个名为BaseCollection的类,该类继承自List,通常列表还需要其他一些操作。一些有用的方法可能包括:

 public class BaseCollection : List<Base>
 {
    public static BaseCollection ToBase<T>(IEnumerable<T> source) where T: Base
    {
       BaseCollection result = new BaseCollection();
       foreach (T item in source)
       {
          result.Add(item);
       }
       return result;
     }

    public static List<T> FromBase<T>(IEnumerable<Base> source) where T: Base
    {
       List<T> result = new List<T>();
       foreach (Base item in source)
       {
          result.Add((T)item);
       }
       return result;
     }


    public static List<T> ChangeType<T, U>(List<U> source) where T: Base where U:Base
    {        
        List<T> result = new List<T>();        
        foreach (U item in source)        
        {           
            //some error checking implied here
            result.Add((T)(Base) item);        
        }        
        return result;      
    }  

    ....
    // some default printing
    public void Print(){...}         
    ....
    // type aware printing
    public static void Print<T>(IEnumerable<T> source) where T:Base {....}
    ....
 }

那将使我能够轻松地将任何后代转换为和从基类集合中转换,并像这样使用它们:
List<Child> children = new List<Child>();
children.Add(new Child { ID = 1, Name = "Tom" });
children.Add(new Child { ID = 2, Name = "Dick" });
children.Add(new Child { ID = 3, Name = "Harry" });

BaseCollection bases = BaseCollection.ToBase(children);
bases.Print();

List<Child> children2 = BaseCollection.FromBase<Child>(bases);
BaseCollection.Print(children2);

不,这个解决方案很糟糕。如果我有几个类myB、myC、myD、myE等都是从myA派生出来的,我需要一个函数,可以将list<T>转换为list<myA>(T可能是myB或myC或myD等),以避免重复编写相同的代码。谢谢。 - Leo Vo
@Nick,这样做可以同时适用于从Dog到Animal的转换和从Animal到Dog的转换(前提是动物确实是狗)。 - SWeko
@Lu Lu:BaseCollection类并不是必需的,但它很好用,因为我可以在里面放置像Print、CalculateCompexAverage、FeedAnimals等方法,无论我需要什么逻辑,这样列表就知道如何表现自己。 - SWeko
@SWeko:不起作用。我收到一个错误:当我调用ToBase函数时,无法将System.Collections.Generic.List<myB>.Enumerator'转换为'System.Collections.Generic.IEnumerable<myA>。你能给我一个例子吗?谢谢。 - Leo Vo
@Lu Lu:尝试了一下,看起来可以,会附上一个例子。 - SWeko
显示剩余4条评论

2

对于.NET 2.0,您可以编写自己的Cast方法,使用Linq代码作为指导:

public static class EnumerableHelper
{
    public static IEnumerable<TResult> Cast<TResult>(IEnumerable source)
    {
        IEnumerable<TResult> enumerable = source as IEnumerable<TResult>;
        if (enumerable != null) return enumerable;
        if (source == null) throw new ArgumentNullException("source");        
        foreach(object element in source)
        {
            yield return (TResult) element;
        }
    }
}

然后按照以下方式使用它:
myA = new List<A>(EnumerableHelper.Cast<A>(myB));   

1
使用引用LINQ实现的源代码来实现其中的部分总是一个好主意。+1 - SWeko

1
    public static List<B> Cast<A,B>(List<A> aLIst) where A : B
    {
        List<B> ret = new List<B>( );

        foreach (A a in aLIst)
        {
            ret.Add(a);
        }

        return ret;
    }    

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接