問題的提出 昨天在qq群問了一個linq的問題被人鄙視了。題目大概類似於 問from...in...select...中in後面如果接的不是集合,而是一個delegate,會怎麼樣??之後就被人鄙視了,一些人嘲笑我工作年頭是混出來的,in後面當然是數據源了,delegate也可以作為數據源,所以當然 ...
- 問題的提出
昨天在qq群問了一個linq的問題被人鄙視了。題目大概類似於
var reuslt=from s in new List<string>() select s;
問from...in...select...中in後面如果接的不是集合,而是一個delegate,會怎麼樣??之後就被人鄙視了,一些人嘲笑我工作年頭是混出來的,in後面當然是數據源了,delegate也可以作為數據源,所以當然可以了。無奈,只能百度——在微軟的官網上查到瞭如下信息:
!!!!!!!!!我的親娘啊,我現在的代碼中from in select 子句的in後面已經跟了delegate,並且是可行的。難道delegate繼承自IEnumerable??
打死也不信。微軟官網在說謊。那真實的情況是什麼樣的呢,後來我終於在源碼中找到了一個自認為合理的解釋,或許這就是from in select 子句的本質,現在分享給大家,如果事實不是這樣,歡迎指正。
- 問題的本質
from in select子句肯定會編譯成c#代碼的,會編譯成什麼呢?我的猜測是這個子句的三個關鍵字會一起編譯。後來結合源碼,分析到其實只要in後面的數據類型Tin實現擴展方法
public static T3 Select<T1, T2,T3>(this Tin tin, Func<T1, T2> selector)
只要實現這個擴展方法,T2類型就可以放到in後面作為數據源。而T1類型就是from子句對象的類型,而select子句的lambda表達式對應的就是Func<T1,T2>selector.
select子句的類型和lambda表達式的入參是一致的。而select返回的類型,不一定是最終返回的類型,而Select擴展方法的返回值會作為最終的返回類型。
多說也不明白,還是給大家上示例代碼,一看就明白了。
class Program { static void Main(string[] args) { var result = from s in new TestApp() { A = 2 } select s; Console.WriteLine(result.GetType() + " " + result); Console.ReadLine(); var reuslt = from s in new List<string>() select s; } } public class TestApp { public int A { get; set; } } public static class SelectExtension { public static string Select(this TestApp app, Func<int, int> selector) { return "hello,你是" + selector(app.A).ToString(); } }
- 最後的心得
1,qq群很少能夠幫上你忙得,官方文檔也是不可靠的。
2,常識很可能是假的
3,有空還是多看看開源代碼,那是真的