2010-04-06 92 views
4

我有一個類Something,它實現了ISomething。我如何將IQueryable<Something>轉換成IQueryable<ISomething>。當我嘗試轉換時,我可以編譯,但轉換的結果始終爲NULL。如何作爲IQueryable返回IQueryable <Something><ISomething>

背景:我做的,這是因爲我的Something類是CodeSmith中生成的類(PLINQO模板),有映射表裝飾,方法等我ISomething接口的原因是「POCO風格」,因爲它是愚蠢的,並簡單地反映了Something類的屬性。它也存在於它自己的命名空間中。我正在這樣做,所以我不必引用從我的服務層持有Something類的程序集。包含Something類的程序集現在只需要在我的存儲庫層中引用。

回答

9

您可以使用LINQ法鑄造

IQueryable<Something> something = ... 
IQueryable<ISomething> casted = something.Cast<ISomething>(); 
0

怎麼沒有 - 而是爲什麼:

通用協方差 - 這種聯繫將有助於解釋:

C# Generic Covariance

+2

解釋答案,而不是爲什麼需要答案。而且你會更好地鏈接到Eric Lippert的主題系列。 – 2010-04-06 17:05:32

+0

@Joel:你有任何機會鏈接到系列? – 2010-08-06 13:13:10

+0

我可以給整個系列沒有一個好的鏈接。我知道這個StackOverflow答案有一個索引:http:// stackoverflow。COM /問題/ 2184551 /差之間的協方差,禁忌方差/ 2556675#2556675 – 2010-08-06 13:30:36

1

有是你在回答這個question時遇到的協方差問題的一個很好的解釋。

11

爲了理解這裏發生了什麼,從類型系統的角度來看這很重要。對於類型系統,SomethingISomething是具有類似繼承關係的兩種類型(實現不完全是繼承,但是關閉)。通用類型IQueryable<Something>IQueryable<ISomething>沒有這種關係。它們是兩種完全不同的類型,屬於繼承樹(包含IQueryable的分支)完全不同的部分,而不是Something或ISomething。

所以從IQuerable<Something>鑄造IQueryable<ISomething>的時候,儘可能的類型系統而言,你不妨試着投從IQueryable<double>IQueryable<IDataRecord>。結果是一樣的:它不知道如何進行該轉換,因此as運算符返回null。

一個解決這個問題(不被別人所指示的問題本身,)稱爲協方差實現在C#4.0。 .Net Type Variance允許類型系統對特殊化相同泛型的兩種不同類型之間的關係具有有限理解,以便當從一個類型投射到另一個時,類型可以變化(注意根字這裏)。

對於.Net 4之前的代碼,您必須使用類似.Cast<T>()擴展方法的內容。但是這不太理想,因爲它強制實際的投射操作,其中類型的變化讓框架使用已經存在的實際類型。