开发者

Casting List<x> to List<y>

The following code works:

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

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

So naturally you'd think that this code w开发者_JS百科ould work too:

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

But I get the error Invalid cast operation - does anybody know why that might happen?

UPDATE

tblStocks is a list of LINQ to SQL object, tblStock.

JsonStock is a simplified version of the tblStock class and gets returned to a webpage as a JSON object.

The following operator was built to do the casting:

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


Cast is used to change a non-generic collection into a generic one, i.e. it performs an unboxing operation. It can't be used the way you want.
When you have a look at the implementation of Cast and the CastIterator it uses, you see, that it takes an object and casts it to the specified type:

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

This only works if current really is a TResult. No custom conversions are applied in this case.
This is the default behavior, you can test it yourself:

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

What you want is best achieved with a simple Select if tblStocks is a generic enumerable:

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

Or, if tblStocks is a non-generic enumerable, you need to combine Cast and Select:

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

This will first unbox the objects in tblStocks to their real type (tblStock) and then cast it to the type you want (JsonStocks).


implicit and explicit conversion operators are ignored by Cast. In your case that means that

 public static explicit operator JsonStock(tblStock stock)

is ignored by Cast they are however not ignored in the foreach case


Instead of using Cast, consider using OfType. In Cast, if the item you are processing isn't the destired type, you will get the InvalidCastException. With OfType, it will trap for invalid cast and only return items that actually are the type that you are looking for.

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

If you return empty lists however, I would suspect that your tblStocks actually is not returning JsonStocks and you are trying to project some other type (tblStock?) into a DTO (JsonStock). If the later is the case, you need to use Select to project into the new type from the underlying type.

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


Ahhh, the wonders of explicit operator overloads.

So to fix your problem you might want to call a Select beforehand.

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

However i'd say that this operator overload is something you should get rid of. Consider replacing it with a copy constructor like implementation

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


  • tblStocks.Cast<JsonStock>() performs a cast.
  • (JsonStock) item performs a cast or applies a custom-defined conversion.

Since tblStock is a LINQ to SQL class and JsonStock is a custom class created by you, none is a subtype of the other. Thus, you cannot cast between the two.

To fix this, you can use the Select clause of LINQ and manually convert the elements:

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

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜