.NET 9.0 में LINQ performance सुधार
(blog.ndepend.com)-.NET 9.0 कई सामान्य LINQ scenarios में .NET 8 की तुलना में execution time को काफी कम करता है, और कुछ benchmarks में allocation भी हटा देता है
- array या
List<T>को iterate करते समयTryGetSpan()सेReadOnlySpan<T>प्राप्त कर iteration cost घटाना प्रमुख सुधारों में से एक है TryGetSpan()type comparison सेTSource[]औरList<TSource>की पहचान करता है, लेकिनList<T>की internal array को span के रूप में लेना capacity बदलने पर invalidate हो सकने वाला Unsafe-श्रेणी का optimization है -.NET 9 का LINQ सामान्य call chains को पहचानकर specialized iterator बनाता है, औरCount(),First(),Last(),ElementAt(),Sum()जैसे terminal methods में अतिरिक्त optimization लागू करता है- सिर्फ migration और recompilation से भी कुछ LINQ performance improvements मिल सकते हैं, और इसमें SIMD उपयोग तथा empty sequence की early detection जैसे optimizations भी शामिल हैं
arrays और lists पर iteration तेज़ क्यों हुआ
- पहला benchmark
Enumerable.Range(1, 10_000).ToArray()कोIEnumerable<int>के रूप में रखकरCount,All,Any,First,Single,Lastचलाता है और .NET 8 व .NET 9 की तुलना करता है - BenchmarkDotNet का उपयोग किया गया है, और project को
net8.0;net9.0target करना चाहिए तथा Release mode में compile करना चाहिए - .NET 9 में कई methods का execution time काफी घटता है और allocation भी समाप्त हो जाता है
LinqCount: 16,198.490 ns से 3,043.563 ns, 32 B allocation से बिना allocationLinqAny: 17,096.735 ns से 2,483.927 ns, 32 B allocation से बिना allocationLinqFirst: 15,289.747 ns से 2,243.341 ns, 32 B allocation से बिना allocationLinqSingle: 21,684.114 ns से 4,884.329 ns, 32 B allocation से बिना allocationLinqAll: 10.588 ns से 2.562 ns, 32 B allocation से बिना allocationLinqLast: 15.967 ns से 6.918 ns
TryGetSpan() क्या फर्क लाता है
- performance सुधार का मुख्य कारण
TryGetSpan()का उपयोग है - अगर iterate किया जाने वाला enumerable array या list हो, तो
TryGetSpan()ReadOnlySpan<T>लौटाता है जिससे iteration तेज़ हो जाती है - core branching code
source.GetType() == typeof(TSource[])याsource.GetType() == typeof(List<TSource>)की जांच के बाद span प्राप्त करता है- array को
Unsafe.As<TSource[]>(source)से संभाला जाता है - list के लिए
CollectionsMarshal.AsSpan(Unsafe.As<List<TSource>>(source))से internal array पर span लिया जाता है
- array को
- code में
source.GetType()दो बार call होता है और casting के बाद null check से नहीं निपटा जाता, लेकिन .NET performance experts ने C# compiler और JIT optimizations को ध्यान में रखकर यह तरीका चुना है - अत्यधिक optimized .NET stack में micro-optimization कई बार सतह पर दिखने वाली बातों से अलग नतीजे दे सकती है
CollectionsMarshal.AsSpan() की सीमाएँ
List<TSource>अंदरूनी रूप से एक array को reference करता है, और list की capacity बढ़ने या घटने पर नया array बनाकर उसी को reference करता हैCollectionsMarshal.AsSpan(Unsafe.As<List<TSource>>(source))इस internal array सेSpan<TSource>प्राप्त करता है- अगर list capacity किसी भी तरह बदलती है, तो इस तरीके से मिला array invalidate हो सकता है
- इस सीमा के कारण
yieldजैसी deferred iteration वाली कुछEnumerableoperations के लिए इस optimization पर निर्भर रहना कठिन है System.Runtime.CompilerServices.Unsafeनाम ही इस जोखिम की ओर संकेत करता है
TryGetSpan() call का दायरा
- NDepend से
System.Linq.dllको scan करकेTryGetSpan()के direct और indirect callers देखे गए - analysis के लिए assembly path
C:\Program Files\dotnet\shared\Microsoft.NETCore.App\9.0.0-rc.1.24431.7\System.Linq.dllहै TryGetSpan()से code query बनाकर callers की पहचान की गई, और 56 matching methods को dependency graph में export किया गया- कई standard
Enumerablemethods collection के array या list होने पर span iteration की कोशिश करते हैं - लेकिन list की internal array को पकड़े रखने का तरीका सुरक्षित नहीं है, इसलिए deferred execution वाली operations पर अब भी सीमाएँ हैं
specialized iterator आधारित optimization
- दूसरा benchmark Consolidate LINQ’s internal IIListProvider/IPartition into base Iterator class PR में दिए गए उदाहरणों का उपयोग करता है
- test cases में
Distinct().First(),Append().Select().Last(),Reverse().Count(),DefaultIfEmpty().Select().ElementAt(),Skip().Take().ElementAt(),Union().First(),Select().Where().Select().Sum()आदि शामिल हैं - .NET 9 में कुछ call chains बेहद तेज़ हो जाती हैं
DistinctFirst: 65.318 ns से 11.192 ns, 328 B allocation से बिना allocationAppendSelectLast: 4,122.007 ns से 2.661 ns, 144 B allocation से बिना allocationDefaultIfEmptySelectElementAt: 4,090.818 ns से 5.724 ns, 144 B allocation से बिना allocationRangeUnionFirst: 66.309 ns से 6.193 ns, 344 B allocation से बिना allocationListSkipTakeElementAt: 6.268 ns से 2.916 nsRangeReverseCount: 11.024 ns से 6.134 ns
- इसके उलट
SelectWhereSelectSum.NET 8 के 3,959.622 ns से .NET 9 में 4,460.008 ns तक धीमा हुआ, और 112 B allocation भी बना रहा
सामान्य LINQ chains की पहचान
- .NET performance team ने code को सामान्य LINQ call chains पहचानने के लिए डिजाइन किया है
- किसी खास chain का पता चलते ही अधिक कुशल तरीके से workflow संभालने वाला specialized iterator बनाया जाता है
- जब chain
Count(),First(),Last(),ElementAt(),Sum()जैसे methods पर खत्म होती है, तब अतिरिक्त optimization संभव होती है - उदाहरण के लिए
OrderBy(criteria).First()कोMin(criteria)की तरह execute होने के लिए optimize किया जा सकता है
Iterator<T> और derived classes की संरचना
- LINQ के अंदर abstract base class
Iterator<T>और उसकी 40 derived classes हैं - ये classes सभी
Enumerableclass के भीतर nested हैं Iterator<T>एक abstract class है, लेकिन methods virtual हैं, इसलिए derived classes सिर्फ ज़रूरी methods को override करती हैं- यही संरचना हर call chain के लिए specialized behavior रखने का आधार बनती है
ListWhereSelectIterator<TSource, TResult> उदाहरण
ListWhereSelectIterator<TSource, TResult>list परWhere(...).Select(...)chain को एक ही iterator में संभालता है- यह iterator
ListWhereIterator<TSource, TResult>केSelect()override में बनता है ListWhereIterator<TSource>तब बनता है जबEnumerable.Where()जांचता है कि sourceList<TSource>है या नहींListWhereSelectIterator<TSource, TResult>TryGetFirst()याTryGetLast()जैसे methods को override नहीं करता- performance सुधार का मुख्य बिंदु यह है कि list पर बहुत सामान्य
Where(...).Select(...)chain को दो iterators की जगह एक iterator में जोड़ दिया गया हैMoveNext()के भीतर_predicateऔर_selectorदोनों delegates साथ में call होते हैं
IListSkipTakeIterator<TSource> उदाहरण
IListSkipTakeIterator<TSource>लागू हो सकने पर बनाया जाने वाला specialized iterator हैMoveNext()_state - 1को list के 0-based index की तरह उपयोग करता है- अलग index field रखना पढ़ने में आसान होता, लेकिन iterator field size घटाने के लिए
_stateमें bias डालकर store किया गया है - इस iterator का optimization
_minIndexInclusiveऔर_maxIndexInclusiverange के बाहर के elements को बेवजह iterate न करने में है
सिर्फ migration से मिलने वाले अतिरिक्त optimizations
- .NET 9 में कई सामान्य LINQ scenarios और तेज़ हो गए हैं
- नए .NET version के सुधार पाने के लिए ज़रूरी काम migration और recompilation है
- LINQ को अन्य तरीकों से भी optimize किया गया है
- integer sequences के sum जैसे मामलों में जहाँ संभव हो SIMD का उपयोग किया जाता है
- empty sequences को जल्दी पहचान लेने से enumeration cost कम होती है
- DeepDotnet videos Scott Hanselman और Stephen Toub के साथ .NET सीखने की सामग्री के रूप में देखे जा सकते हैं
1 टिप्पणियां
Hacker News की रायें
मेरे हिसाब से LINQ का सबसे उपयोगी हिस्सा
IQueryableका syntax tree-आधारित extension structure भी नहीं है, और न ही language में built-in syntax, बल्किIEnumerableextension methods हैंपहले इसे कुछ हद तक भ्रमित करने वाले नाम “LINQ to Objects” से बुलाया जाता था, और यह C# को functional style में संक्षेप में लिखने देता है
मूल लेख मुख्य रूप से इन्हीं extension methods की optimizations पर है
Haskell सीखने के बाद ही यह तरीका ठीक से समझ आया, और यह lazy evaluation जैसी Haskell की कुछ खूबियां और pitfalls भी साझा करता है
बिना सोचे-समझे इस्तेमाल करने पर code कठिन और धीमा हो सकता है, इसलिए अगर team में basic functional idioms और lazy evaluation समझने वाला कोई नहीं है, तो मैं इसकी सिफारिश नहीं करूंगा
IEnumerableऔरIQueryableपर LINQ extensions के functional पहलू को पसंद करता हूंइनके बारे में reason करना आसान होता है, और Entity Framework जैसी जगहों में यह हमेशा सबसे तेज विकल्प नहीं होता, लेकिन आम तौर पर काफी अच्छा विकल्प होता है
EF के बजाय Dapper इस्तेमाल करना भी मुझे पसंद है
हालांकि C# projects में abstraction layers बेवजह बहुत ज्यादा हो जाने की प्रवृत्ति होती है, और “enterprise” development आम तौर पर देखने में तकलीफदेह होता है
naming में थोड़ा non-standard हिस्सा है, लेकिन जरूरत की सारी चीजें मौजूद हैं
Eric Lippert ने LINQ से जोड़कर monads समझाने वाली एक शानदार लेख-श्रृंखला लिखी थी: https://ericlippert.com/2013/04/02/monads-part-twelve/
मुझे host language के अंदर एक और “built-in” language आना पसंद नहीं है, और अंतिम परिणाम भी आखिरकार C# में ही लौटना होता है
Entity Framework या Dapper जैसे ORM इस्तेमाल न करने पर भी, SQL समेत data access logic को अलग abstracted project में रखना बेहतर होता है
इससे वह पूरे application में नहीं फैलता, और अगर कभी दूसरा RDBMS चाहिए हो तो उसे बदला जा सकता है
20 साल में असल में ऐसा सिर्फ एक बार हुआ है, लेकिन फिर भी
junior developers जब LINQ इस्तेमाल करते हैं, तो profiler और debugger जोड़ देने से उन्हें अंदर क्या हो रहा है यह समझने में मदद मिलती है
कभी-कभी पहले
forloop और सामान्य C# logic से लिखवाकर फिर LINQ implementation से तुलना कराना भी उपयोगी होता है, ताकि वे दोनों approaches के फायदे-नुकसान देख सकेंquery syntax
IEnumerableके लिए hardcoded नहीं है; बस default behavior वैसा है, और इसे लगभग कहीं भी इस्तेमाल किया जा सकता हैयह operator overloading जैसा थोड़ा काम करता है
[1]: https://github.com/acple/ParsecSharp/blob/da8d0cb9ec39e28dd9...
समझ नहीं आता कि dotnet team tooling में और ज्यादा resources और time क्यों नहीं लगाती
doctest और documentation generation, actual code के पास ही बेहतर और तेज unit tests लिखने की capability, source code accessibility, F12 दबाने पर DLL decompile किए बिना काम करने वाला environment, और
pkg.go.devयाdocs.rsजैसा packages और docs का central hub चाहिएज्यादातर NuGet packages में या तो documentation बिल्कुल नहीं होती, या सिर्फ GitHub README होता है, या छोटी-सी wiki होती है
Rust, Go, Java, Python जैसे दूसरे ecosystems इस मामले में कई प्रकाश-वर्ष आगे हैं
लेकिन डरावनी बात यह है कि यह सच के काफी करीब भी लगता है
उदाहरण: https://learn.microsoft.com/en-us/dotnet/api/system.string.s...
NuGet package source के लिए भी Source Link चालू करने पर यह आसानी से संभव है, लेकिन यह अभी relatively नया feature है, इसलिए सभी packages ने इसे लागू नहीं किया है
लगता है आज भी ज्यादातर C# code companies में closed source के रूप में ही लिखा जाता है
अगर Microsoft पिछले कुछ वर्षों की तरह खुलेपन की दिशा में आगे बढ़ता रहा, तो समय के साथ यह बेहतर होगा
इनमें से कुछ features Resharper जैसे tools देते हैं, और सोचता हूं कि कहीं इनके बीच एक-दूसरे के क्षेत्र में दखल न देने का कोई explicit या implicit agreement तो नहीं है
सच कहूं तो C# projects में मैंने जो documentation देखी है, वह ज्यादातर खराब quality की थी, इसलिए आखिर में source code ही देखना पड़ता है
autocomplete tools बहुत होने पर भी पढ़ने में खास मदद नहीं करते, सिर्फ लिखने में मदद करते हैं—मेरा अनुभव यही है
https://github.com/EWSoftware/SHFB
इसे recommend करूं या नहीं, पक्का नहीं
मैंने खुद आजमाया और फिर वापस हटा दिया; शायद build artifact caching खराब होने की वजह से tests ज्यादा समय लेते लग रहे थे
इसे “LINQ performance improvement” कहने के बजाय “अपने
Listimplementation की performance improvement” कहना ज़्यादा सही होगालगता है Microsoft आम सुधारों की बजाय उन हिस्सों को बेहतर बनाने में समय लगाता है जिनकी उन्हें खुद जरूरत होती है
LINQ, खासकर method extensions नहीं बल्कि query syntax, में निवेश की जरूरत है
मुख्य रूप से lambda allocations और, अगर संभव हो, compile time पर lambda reduction की जरूरत है
value-type local lambdas या ऐसी strategy चाहिए जिससे lambda allocations अभी की तरह overhead न बनें
LINQ variables में भी अब wildcard (
_) support होना चाहिए, लेकिन जब lambdas में इसे लाया गया तो इसे पूरी तरह नजरअंदाज कर दिया गयासाथ ही LINQ expression के आखिरी item के रूप में
select ...के बजायIEnumerable,Optionजैसे lifted types इस्तेमाल किए जा सकने चाहिएकुछ use cases में
selectगैर-जरूरी overhead बनाता है, और tail-recursive LINQ expressions जैसी चीजों को भी सीमित करता हैमेरी library जैसी libraries, जो LINQ पर पूरी तरह निर्भर हैं लेकिन
IEnumerable,IQueryable, LINQ extensions इस्तेमाल नहीं करतीं, लगातार नजरअंदाज की जाती हैंक्योंकि Microsoft सिर्फ अपने projects की performance improvement पर ध्यान देता है
इसका अच्छा उदाहरण improved lambda inference है
इसे इसलिए आगे बढ़ाया गया क्योंकि ASP.NET Core की Minimal API को इसकी जरूरत थी
लगता है language और framework features का बड़ा हिस्सा community needs से ज्यादा Microsoft की internal needs से चलता है
सबसे खराब बात यह है कि LINQ extensions
Select,SelectMany,Whereही नहीं, बल्किGetAwaiterजैसे magic methods का set लगातार बढ़ता जा रहा हैMicrosoft इस magic को हटाने के लिए सच में जरूरी higher-kinded traits जोड़ने के बजाय, अपने लिए, मुख्यतः compiler के लिए, features जोड़ रहा है
इसलिए सब कुछ weakly typed ही रह जाता है, और compiler बस मोटे तौर पर ही चीजें पकड़ पाता है
LINQ languages के बीच मुख्य differentiators में से एक है, लेकिन C# 3 के बाद से इसे लगभग छोड़ दिया गया है
अब भी LINQ को list traversal, खासकर अपने list implementation traversal के लिए ही उपयोगी मानना सच में अफसोसजनक है
performance improvements के लिए आभारी हूं और इससे कई users को मदद मिलेगी, लेकिन focus हमेशा इतना narrow रहता है कि इसकी potential सीमित हो जाती है
[1] https://github.com/louthy/language-ext/
dotnet/runtimeमें issue खोलना या PR भेजना अच्छा होगाarticle में बताई गई LINQ performance improvements में से काफी इसी तरह आई थीं
इसमें कई
usingstatements हैं, जो उन लोगों के लिए बड़ी समस्या नहीं है जो project को जरूरत के हिसाब से छोटे हिस्सों में बांटना और concerns अलग करना समझते हैंलेकिन ज्यादातर developers projects को इस तरह structure नहीं करते, और ऐसी छोटी चीजें average developer के लिए barrier बन सकती हैं
junior developers अक्सर standard LINQ syntax और methods, खासकर performance में भी पहले से struggle करते हैं
README में इस बात का जिक्र होना अच्छा है
आम तौर पर लोग library को “बेचने” में लगे रहते हैं, लेकिन आपने सच में लिखा है कि यह किसमें strong है और इसका purpose क्या है, यह पसंद आया
non-idiomatic होने का जिक्र भी C#/.NET सीखने वालों के लिए समस्या हो सकता है
Microsoft शायद चाहता होगा कि tools और language कुछ खास practices follow करें, और functional programming के हिसाब से natural naming, Microsoft के लिए improvements पर विचार करते समय काफी बड़ा hurdle लग सकता है
मैंने repository को star किया है, और आपने जो बनाया है उसमें मेरी काफी दिलचस्पी है
हाल में बनाए गए कुछ बड़े applications में मैंने
Optionसे मोटे तौर पर मिलता-जुलताResulttype इस्तेमाल किया थालेकिन library को फिर से देखकर लगा कि मैं खुद को functional programming काफी जानने वाला समझता था, जबकि असल में ऐसा नहीं है
C# मुझे काफी अच्छी तरह आता है और मैंने complex काम भी किए हैं, लेकिन functional programming पर बहुत पढ़ने के बावजूद इसे सीखना अब भी मुश्किल है, और F# For Fun And Profit ही अब तक सबसे ज्यादा समझ में आया
कुल मिलाकर इसका मतलब यह नहीं कि आप कुछ गलत कर रहे हैं
Microsoft अपने ecosystem के बहुमत, यानी average या beginner developers, को target करेगा
उम्मीद है इस library को internal improvements का फायदा मिल सके
साफ दिखता है कि इसमें बहुत समय लगाया गया है, और सिर्फ GitHub stars की संख्या भी यह बताने के लिए काफी है कि लोग इसे सच में इस्तेमाल कर रहे हैं और इससे मदद पा रहे हैं
अगर मेरी बात dismissive लगी हो तो माफ करें, लेकिन आपका काम interesting है और documentation भी ऐसी लगती है कि अनजान concepts को धीरे-धीरे सीखा जा सके
C# जितना ज्यादा F# से उधार ले, उतना बेहतर
इंतजार है कि discriminated unions आखिरकार C# में आएं ताकि domain modeling ठीक से की जा सके
हर बार सवाल उठता है, “बस F# क्यों नहीं इस्तेमाल करते?”
C# कई सालों से catch-up खेल रहा है
अगर .NET ecosystem में कई innovations F# आगे बढ़ा रहा था और features के मामले में कई साल आगे था, तो उस मेहनत को usage से reward क्यों नहीं किया जाता, यह सोचने वाली बात है
अगर आप language development की कोई direction चाहते हैं तो उसे अपने actual choices से encourage करना चाहिए
Java ecosystem में यह तरीका काम कर चुका है, और अब Java भी improve हो रहा है
market बड़ा होने पर engineering effort भी बढ़ता है, ऐसा positive feedback loop बन सकता है
कई साल forums पढ़ने पर लगता है कि C# camp “बस” अपने ही camp में रहकर इंतजार करना चाहता है
यह थोड़ा tribalism जैसा दिखता है, जैसे team “C#” हो
दूसरे language ecosystems में ऐसी culture कम ही दिखी, और impression यह है कि अगर F# .NET के अलावा किसी और ecosystem में होता तो शायद बहुत पहले फल-फूल चुका होता
engineering या scientific code की maintainability कहीं आसान हो जाएगी
practical example: https://chrlschn.dev/blog/2024/07/csharp-discriminated-union...
[0] https://github.com/mcintyre321/OneOf
[1] https://github.com/domn1995/dunet
दूसरी भाषाओं या ecosystems में काम करते समय जिस चीज़ की सबसे ज़्यादा कमी महसूस होती है, वह LINQ है
standard library में ऐसी functionality होना वाकई बहुत अच्छा है, और दी गई constraints के भीतर इसे खूबसूरती से design किया गया है
.NET 9 में सभी performance improvements को कवर करने वाले सालाना, किताब जितने लंबे article में इससे जुड़ा section है
https://devblogs.microsoft.com/dotnet/performance-improvemen...
अजीब तरह से HN ने इसे फिर से submit करने की अनुमति नहीं दी, इसलिए article front page पर नहीं आ पाया और दब गया
LINQ की आदत पड़ जाए, और आम तौर पर उन domains में काम करने लगें जहाँ LINQ चमकता है, तो फिर किसी और तरीके पर लौटने का मन नहीं करता
LINQ तुम्हें जकड़ लेगा, और तुम LINQ के बिना वाले environments से चिढ़ने लगोगे
सोच रहा हूँ कि dotnet से end-to-end web development सीखने के लिए कोई comprehensive book या tutorial है क्या
जो चीज़ें मिलीं, उनमें से ज़्यादातर या तो बहुत basic थीं, या पुरानी, या low quality
निजी तौर पर मुझे लगता है यह Silverlight जैसा रास्ता लेगा
पुरानी technologies भी .NET 9 में अब भी मौजूद हैं, काम करती हैं और maintain की जा रही हैं
आजकल .NET से web development करने का मतलब ज़्यादातर HTTP/JSON/REST API बनाना और उसे अपनी पसंद के front-end framework से जोड़ना है
मेरे मामले में मैं React या NextJS इस्तेमाल करता हूँ
search terms के लिए ASP.NET WebApi या ज़्यादा modern तौर पर ASP.NET Minimal API अच्छे रहेंगे
Razor के साथ .NET MVC server-side rendering भी अब भी संभव है
यह ASP.NET MVC की markup language है, इसलिए “ASP.NET MVC Razor” से खोजें
अच्छा हो या बुरा, .NET में web applications बनाने का तरीका ASP.NET ही लगभग default answer जैसा लगता है
alternatives की कमी थोड़ी suspicious है, लेकिन
“ASP.NET Core in Action” के author Andrew Lock वाला podcast सुना, और वे विषय को अच्छी तरह जानने वाले लगे
अभी किताब नहीं पढ़ी है, लेकिन शायद वही किताब हो सकती है जिसकी तलाश है
1: https://dotnetcore.show/season-6/navigating-the-aspnet-core-...
2: https://www.manning.com/books/asp-net-core-in-action-third-e...
server पर ASP.NET के ऊपर Giraffe चला सकते हैं, और यह C# जैसी performance देने वाली functional programming layer है
front-end पर आप असली functional programming language में React लिख सकते हैं
स्वाभाविक है कि front-end और back-end के बीच F# code भी share कर सकते हैं
किताबों में Mark J Price की “C# 12 and .NET 8 - Modern Cross-Platform Development Fundamentals - Eighth Edition: Start building websites and services with ASP.NET Core 8, Blazor, and EF Core 8”, और Xiaodi Yan की “Web API Development with ASP.NET Core 8: Learn techniques, patterns, and tools for building high-performance, robust, and scalable web APIs” हैं
tutorials में YouTube पर IAmTimCorey और Shawn Wildermuth की series हैं
.NET backend और JS front-end combination के लिए Minimal API इस्तेमाल करने वाले resources देखें
MVC भी अच्छा है, लेकिन backward compatibility का बोझ ज़्यादा है, इसलिए Minimal API आया
annotations के इस spaghetti pile से बेहतर तरीका होना चाहिए
modern .NET code देखते ही मेरी आँखें दुखने लगती हैं
unit test और benchmarking code आम तौर पर कुछ हद तक spaghetti जैसा दिखता ही है
फिर भी actual business logic में ऐसा PR मैं approve नहीं करूँगा
अगर आपको सच में नापसंद है, तो AspNetCore जैसी चीज़ भी बिना किसी attribute को छुए इस्तेमाल कर सकते हैं
मैं attributes का लगभग इस्तेमाल नहीं करता
Count(),First(),Last(),ElementAt(),Sum()जैसे methods पर chain खत्म होने पर और optimizations संभव हैं, और उदाहरण के लिएOrderBy(criteria).First()कोMin(criteria)की तरह execute होने के लिए optimize किया जा सकता है—यह हिस्सा उपयोगी हो सकता हैलेकिन शुरुआत से ही बेहतर code लिखना सही है
dynamically generated chains के लिए यह interesting होगा, लेकिन अपने हाथ से लिखे code में अगर ऐसी operations कर रहे हैं तो यह थोड़ा टेढ़ा positive reinforcement जैसा लगता है
library inefficient patterns को पहचानकर ठीक कर रही है
कम से कम उम्मीद है कि underlying code सुधारने का feedback मिले