将List <x>转换为List <y> </y> </x>

时间:2011-09-01 11:51:34

标签: c# list casting

以下代码有效:

List<JsonStock> stock = new List<JsonStock>();

foreach(tblStock item in repository.Single(id).tblStocks)                
    stock.Add((JsonStock) item);

很自然地,你会认为这段代码也会起作用:

List<JsonStock> stock = repository.Single(id).tblStocks.Cast<JsonStock>().ToList()

但是我收到了错误Invalid cast operation - 有人知道为什么会发生错误吗?

更新

tblStocks 是LINQ to SQL对象列表,tblStock。
JsonStock 是tblStock类的简化版本,并作为JSON对象返回到网页。

构建以下运算符来进行转换:

public partial class tblStock{
    public static explicit operator JsonStock(tblStock stock){
        JsonStock item = new JsonStock
        {
            boxes = stock.boxes,
            boxtype = stock.tblBoxType.name,
            boxtype_id = stock.boxtype_id,
            grade = stock.grade,
            packrate = stock.packrate,
            weight = stock.weight
        };

        return item;
    }
}

5 个答案:

答案 0 :(得分:6)

Cast用于将非泛型集合更改为通用集合,即它执行取消装箱操作。它不能以你想要的方式使用。
当您查看Cast的实现及其使用的CastIterator时,您会看到它需要一个对象并将其强制转换为指定的类型:

foreach (object current in source)
{
    yield return (TResult)current;
}

仅当current确实是TResult时才有效。在这种情况下,不会应用自定义转换 这是默认行为,您可以自己测试:

double d = 0.0;
object tmp = d;
int i = (int)tmp; // throws the same exception you are getting

如果Select是通用可枚举的,那么使用简单的tblStocks可以最好地实现您的目标:

List<JsonStock> stock = repository.Single(id).tblStocks
                                  .Select(x => (JsonStock)x).ToList();

或者,如果tblStocks是非通用的可枚举,则需要合并CastSelect

List<JsonStock> stock = repository.Single(id).tblStocks.Cast<tblStock>()
                                  .Select(x => (JsonStock)x).ToList();

这将首先将tblStocks中的对象解包为真实类型(tblStock),然后将其转换为您想要的类型(JsonStocks)。

答案 1 :(得分:2)

隐式和显式转换运算符为ignored by Cast。在你的情况下,这意味着

 public static explicit operator JsonStock(tblStock stock)
Cast会忽略

,但在foreach案例中不会忽略它们

答案 2 :(得分:1)

请考虑使用OfType,而不是使用Cast。在Cast中,如果您正在处理的项目不是destired类型,您将获得InvalidCastException。使用OfType,它将捕获无效的强制转换并仅返回实际上是您正在寻找的类型的项目。

List<JsonStock> stock = repository.Single(id).tblStocks.OfType<JsonStock>().ToList() 

如果你返回空列表,我会怀疑你的tblStocks实际上没有返回JsonStocks并且你试图将其他类型(tblStock?)投影到DTO(JsonStock)中。如果是后一种情况,则需要使用Select从基础类型投射到新类型。

List<JsonStock> stock = repository.Single(id).tblStocks
                        .Select(stock => new JsonStock 
                             { 
                               Id = stock.Id,
                               Val1 = stock.Val1,
                               Val2 = stock.Val2,
                               ...
                             }
                         .ToList();

答案 3 :(得分:1)

  • tblStocks.Cast<JsonStock>()执行演员表。
  • (JsonStock) item执行广告或应用自定义转化

由于tblStock是一个LINQ to SQL类,而JsonStock是由您创建的自定义类,因此没有一个是另一个的子类型。因此,你不能在两者之间施展。

要解决此问题,您可以使用LINQ的Select子句并手动转换元素:

 List<JsonStock> stock = repository.Single(id).tblStocks
     .Select(item => (JsonStock) item).ToList();

答案 4 :(得分:1)

啊,显式运算符重载的奇迹。

因此,为了解决您的问题,您可能需要事先调用Select。

List<JsonStock> stock = repository.Single(id).tblStocks.Select(x => (JsonStock)x).ToList() 

但是我会说这个操作符过载是你应该摆脱的东西。考虑将其替换为类似实现的复制构造函数

class JsonStock
{
     public JsonStock(tblStock other)
     {
          // copy values here
     }
}