2011-09-01 38 views
11

下面的代碼工作:鑄造名單<x>列出<y>

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 - 有誰知道爲什麼可能發生?

UPDATE

tblStocks是LINQ到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; 
    } 
} 
+3

「tblStocks」的類型是如何定義的? –

+0

只是一個想法,不知道這個:'repository.Single(id).tblStocks'返回一個數組或列表'JsonStock',所以當你試圖將其作爲'JsonStock'投射時,它會投訴... – Marco

+0

@Marco - no它不應該抱怨。 –

回答

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)。

+2

對於最完整的 – UrbanEsc

1

而不是使用鑄造的,可以考慮使用OfType。在Cast中,如果您正在處理的項目不是所需的類型,則會得到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(); 
1
  • tblStocks.Cast<JsonStock>()執行演員。
  • (JsonStock) item執行轉換或應用自定義轉換

由於tblStock是一個LINQ to SQL類,JsonStock是由您創建的自定義類,所以none都不是另一個的子類型。因此,你不能在兩者之間施放。

爲了解決這個問題,你可以使用LINQ的Select條款和手動轉換的元素:

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

隱性和顯性的轉換操作符是ignored by Cast。在你的情況這意味着

public static explicit operator JsonStock(tblStock stock) 

由演員忽略它們然而,不是在foreach情況下

+0

說誰?如果那是真的,那麼'Enumerable.Cast ()'根本就沒有意義。 http://msdn.microsoft.com/en-us/library/bb341406.aspx不包含任何信息來支持您的聲明。 – VVS

+0

@VVS:你不明白'Enumerable.Cast ()'的用途。輸入是一個非泛型的枚舉。結果是一個泛型的枚舉。此擴展方法的全部目的是從非泛型枚舉中創建強類型枚舉,您知道對象的類型。查看我的答案瞭解更多詳情。 –

+0

@VVS如果仔細閱讀,鏈接確實包含信息來支持我的請求,就像我的答案中的鏈接一樣。 您提供的關於_cast_運算符的鏈接是_conversion_運算符。使用兩者的語法是相同的(SomeType),但不會使它們相同。所以我真的不會得到你的低調 –

1

唉唉,明確運算符重載的奇蹟忽略。

因此,要解決您的問題,您可能需要事先調用Select。

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

但是我會說這個運算符超載是你應該擺脫的東西。考慮用複製構造函數替換它,如實現

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

+1感謝您的解決方案:P – Jimbo