C#泛型类型转换列表<t>到列表&lt;碱基类型&GT; </T>

时间:2011-01-27 03:00:47

标签: c# generics reflection

我如何将List<Car>强制转换为List<MyBaseClass>,在我的List代码实例中将作为对象(程序要求不是故意的),通过这样做,我将检索vehicleId ..

 public Form1()
    {           
        List<Car> lstCar = new List<Car>();
        lstCar.Add(new Car() { Make = "tootay", Model = "camry", VechicleId = 1 });
        lstCar.Add(new Car() { Make = "honda", Model = "civic", VechicleId = 2 });
        VehicleConverter(lstCar);
    }
    public void VehicleConverter(object obj)
    {
      //Want to typecast it to List<MyBaseClass>            
    }        
}

public class MyBaseClass
{        
    public int VechicleId { get; set; }        
}

public class Car:MyBaseClass
{
    public string Make { get; set; }
}

public class Bike : MyBaseClass
{
    public int CC { get; set; }
}

7 个答案:

答案 0 :(得分:6)

这是不可能的。

如果有可能,您可以写下以下内容:

List<Car> carList = new List<Car>();
List<BaseClass> baseList = (List<BaseClass>)carList;
baseList.Add(new Bike());    //I just put a Bike into a List<Car>!

备选方案:

  • 将列表声明为List<BaseCLass>
  • 转换为非通用IList(不推荐)
  • 使用.Net 4的协方差
  • 转换为IEnumerable<BaseClass>
  • 传递列表的类型副本:

    VehicleConverter(lstCar.ConvertAll(c => (BaseClass)c));
    

答案 1 :(得分:3)

您没有提及是否使用.NET 4.0或更早版本,但如果您使用的是.NET 4.0,那么通用接口的新协方差/反差方法功能可能会对您有所帮助。

您发现无法将List<Car>转换为List<MyBaseClass>,但使用.NET 4.0,您可以将IEnumerable<Car>转换为IEnumerable<MyBaseClass>

然后,您可以使用IEnumerable<MyBaseClass>作为参数调用需要List<Car>的函数,而无需执行任何特殊转换或转换代码。

例如,此代码适用于.NET 4.0:

List<Car> lstCar = new List<Car>();
lstCar.Add(new Car() { Make = "tootay", Model = "camry", VechicleId = 1 });
lstCar.Add(new Car() { Make = "honda", Model = "civic", VechicleId = 2 });

VehicleConverter(lstCar);

public void VehicleConverter(IEnumerable<MyBaseClass> vehicles)
{
    var found = vehicles.Where(v => v.VechicleId == 123);
}

我希望这会有所帮助。

答案 2 :(得分:1)

之所以无法做到这一点,是因为你可以运行这样的错误:

var cars = new List<Car>();
var vehicles = (List<MyBaseClass>)cars; // Not possible, but assume it was
vehicles.Add(new Bike());  // Runtime fail because now you are trying to add a bike to a list of cars

答案 3 :(得分:0)

public List<MyBaseClass> VehicleConverter<T>(List<T> obj)
    where T : MyBaseClass
{
    return obj.Cast<MyBaseClass>().ToList();
} 

答案 4 :(得分:0)

您可以尝试使用System.Linq命名空间中的“IEnumerable.Cast&lt; T&gt;()”扩展方法。

以下是msdn文档的链接:http://msdn.microsoft.com/en-us/library/bb341406.aspx

以下是一个例子:

public void VehicleConverter(IEnumerable obj)
{
     IEnumerable<MyBaseClass> enumerable = obj.Cast<MyBaseClass>();
     List<MyBaseClass> list = enumerable.ToList();
}

答案 5 :(得分:0)

这有效

if (obj is List<Car>)
{
    List<MyBaseClass> c = ((List<Car>)obj).ToList<MyBaseClass>();
}

但是你需要为每种类型做这件事。理想情况下,你应该在传递给VehicleConverter之前进行投射。

虽然看起来像一个奇怪的要求,如果你被允许使用它,会建议使用@ yodaj007选项。

答案 6 :(得分:0)

即使我无法将其转换为BaseClass,但我实现了通过Casting&amp; amp;检索vehicleId的目标。反射。

    public void VehicleConverter(object obj)
    {

        Type t = obj.GetType().GetGenericArguments()[0].GetType();
        IList lstVec = ((IList)obj);
        foreach (var k in lstVec)
        {
            PropertyInfo[] p = k.GetType().GetProperties();
            foreach (PropertyInfo pi in p)
                if (pi.Name == "VechicleId")
                    MessageBox.Show(Convert.ToString(pi.GetValue(k, null)));
        }
    }