我正在使用Dapper返回動態對象,有時還會手動映射它們。一切都運轉良好,但我想知道什麼是鑄造法則以及為什麼下面的例子都適用。
(對於這些例子,我使用'StringBuilder'作為我的已知類型,儘管它通常類似於'Product')
Example1:為什麼這會返回一個IEnumerable<dynamic>
即使'makeStringBuilder'顯然返回一個StringBuilder
對象?
示例2:為什麼要構建,但如果它是IEnumerable<StringBuilder>
,則“Example1”不會?
例3:與Example2相同的問題?
private void test()
{
List<dynamic> dynamicObjects = {Some list of dynamic objects};
IEnumerable<dynamic> example1 = dynamicObjects.Select(s => makeStringBuilder(s));
IEnumerable<StringBuilder> example2 = dynamicObjects.Select(s => (StringBuilder)makeStringBuilder(s));
IEnumerable<StringBuilder> example3 = dynamicObjects.Select(s => makeStringBuilder(s)).Cast<StringBuilder>();
}
private StringBuilder makeStringBuilder(dynamic s)
{
return new StringBuilder(s);
}
通過上面的例子,是否有推薦的處理方法?像這樣的鑄造會傷害性能嗎?謝謝!
當您使用dynamic
,即使作為參數,整個表達式也是通過動態綁定處理的,並且會在編譯時產生“動態”(因為它基於其運行時類型)。這包含在C#規範的7.2.2中:
但是,如果表達式是動態表達式(即具有動態類型),則表示它參與的任何綁定應基於其運行時類型(即它在運行時表示的對象的實際類型)而不是比它在編譯時的類型。因此,這種操作的綁定被推遲到在程序運行期間執行操作的時間。這稱為動態綁定。
在您的情況下,使用強制轉換將安全地將其轉換為IEnumerable<StringBuilder>
,並且對性能的影響非常小。 example2
版本比example3
版本稍微高效,但是當以這種方式使用時,它們都具有非常小的開銷。
雖然我不能很好地說出“為什麼”,但我認為你應該能夠將example1寫成:
IEnumerable<StringBuilder> example1 = dynamicObjects.Select<dynamic, StringBuilder>(s => makeStringBuilder(s));
您需要告訴編譯器投影應該採用什麼類型,但我確信其他人可以澄清為什麼它無法推斷出正確的類型。但我相信通過指定投影類型,您可以避免必須實際投射,這應該會產生一些性能優勢。