ParallelEnumerable.cs 332 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091409240934094409540964097409840994100410141024103410441054106410741084109411041114112411341144115411641174118411941204121412241234124412541264127412841294130413141324133413441354136413741384139414041414142414341444145414641474148414941504151415241534154415541564157415841594160416141624163416441654166416741684169417041714172417341744175417641774178417941804181418241834184418541864187418841894190419141924193419441954196419741984199420042014202420342044205420642074208420942104211421242134214421542164217421842194220422142224223422442254226422742284229423042314232423342344235423642374238423942404241424242434244424542464247424842494250425142524253425442554256425742584259426042614262426342644265426642674268426942704271427242734274427542764277427842794280428142824283428442854286428742884289429042914292429342944295429642974298429943004301430243034304430543064307430843094310431143124313431443154316431743184319432043214322432343244325432643274328432943304331433243334334433543364337433843394340434143424343434443454346434743484349435043514352435343544355435643574358435943604361436243634364436543664367436843694370437143724373437443754376437743784379438043814382438343844385438643874388438943904391439243934394439543964397439843994400440144024403440444054406440744084409441044114412441344144415441644174418441944204421442244234424442544264427442844294430443144324433443444354436443744384439444044414442444344444445444644474448444944504451445244534454445544564457445844594460446144624463446444654466446744684469447044714472447344744475447644774478447944804481448244834484448544864487448844894490449144924493449444954496449744984499450045014502450345044505450645074508450945104511451245134514451545164517451845194520452145224523452445254526452745284529453045314532453345344535453645374538453945404541454245434544454545464547454845494550455145524553455445554556455745584559456045614562456345644565456645674568456945704571457245734574457545764577457845794580458145824583458445854586458745884589459045914592459345944595459645974598459946004601460246034604460546064607460846094610461146124613461446154616461746184619462046214622462346244625462646274628462946304631463246334634463546364637463846394640464146424643464446454646464746484649465046514652465346544655465646574658465946604661466246634664466546664667466846694670467146724673467446754676467746784679468046814682468346844685468646874688468946904691469246934694469546964697469846994700470147024703470447054706470747084709471047114712471347144715471647174718471947204721472247234724472547264727472847294730473147324733473447354736473747384739474047414742474347444745474647474748474947504751475247534754475547564757475847594760476147624763476447654766476747684769477047714772477347744775477647774778477947804781478247834784478547864787478847894790479147924793479447954796479747984799480048014802480348044805480648074808480948104811481248134814481548164817481848194820482148224823482448254826482748284829483048314832483348344835483648374838483948404841484248434844484548464847484848494850485148524853485448554856485748584859486048614862486348644865486648674868486948704871487248734874487548764877487848794880488148824883488448854886488748884889489048914892489348944895489648974898489949004901490249034904490549064907490849094910491149124913491449154916491749184919492049214922492349244925492649274928492949304931493249334934493549364937493849394940494149424943494449454946494749484949495049514952495349544955495649574958495949604961496249634964496549664967496849694970497149724973497449754976497749784979498049814982498349844985498649874988498949904991499249934994499549964997499849995000500150025003500450055006500750085009501050115012501350145015501650175018501950205021502250235024502550265027502850295030503150325033503450355036503750385039504050415042504350445045504650475048504950505051505250535054505550565057505850595060506150625063506450655066506750685069507050715072507350745075507650775078507950805081508250835084508550865087508850895090509150925093509450955096509750985099510051015102510351045105510651075108510951105111511251135114511551165117511851195120512151225123512451255126512751285129513051315132513351345135513651375138513951405141514251435144514551465147514851495150515151525153515451555156515751585159516051615162516351645165516651675168516951705171517251735174517551765177517851795180518151825183518451855186518751885189519051915192519351945195519651975198519952005201520252035204520552065207520852095210521152125213521452155216521752185219522052215222522352245225522652275228522952305231523252335234523552365237523852395240524152425243524452455246524752485249525052515252525352545255525652575258525952605261526252635264526552665267526852695270527152725273527452755276527752785279528052815282528352845285528652875288528952905291529252935294529552965297529852995300530153025303530453055306530753085309531053115312531353145315531653175318531953205321532253235324532553265327532853295330533153325333533453355336533753385339534053415342534353445345534653475348534953505351535253535354535553565357535853595360536153625363536453655366536753685369537053715372537353745375537653775378537953805381538253835384538553865387538853895390539153925393539453955396539753985399540054015402540354045405540654075408540954105411541254135414541554165417541854195420542154225423542454255426542754285429543054315432543354345435543654375438543954405441544254435444544554465447544854495450545154525453545454555456545754585459546054615462546354645465546654675468546954705471547254735474547554765477547854795480548154825483548454855486548754885489549054915492549354945495549654975498549955005501550255035504550555065507550855095510551155125513551455155516551755185519552055215522552355245525552655275528552955305531553255335534553555365537553855395540554155425543554455455546554755485549555055515552555355545555555655575558555955605561556255635564556555665567556855695570557155725573557455755576557755785579558055815582558355845585558655875588558955905591559255935594559555965597559855995600560156025603560456055606560756085609561056115612561356145615561656175618561956205621562256235624562556265627562856295630563156325633563456355636563756385639564056415642564356445645564656475648564956505651565256535654565556565657565856595660566156625663566456655666566756685669567056715672567356745675567656775678567956805681568256835684568556865687568856895690569156925693569456955696569756985699570057015702570357045705570657075708570957105711571257135714571557165717571857195720572157225723572457255726572757285729573057315732573357345735573657375738573957405741574257435744574557465747574857495750575157525753575457555756575757585759576057615762576357645765576657675768576957705771577257735774577557765777577857795780578157825783578457855786578757885789579057915792579357945795579657975798579958005801580258035804580558065807580858095810581158125813581458155816581758185819582058215822582358245825582658275828582958305831583258335834583558365837583858395840584158425843584458455846584758485849585058515852585358545855585658575858585958605861586258635864586558665867586858695870587158725873587458755876587758785879588058815882588358845885588658875888588958905891589258935894589558965897589858995900590159025903590459055906590759085909591059115912591359145915591659175918591959205921592259235924592559265927592859295930593159325933593459355936593759385939594059415942594359445945594659475948594959505951595259535954595559565957595859595960596159625963596459655966596759685969597059715972597359745975597659775978597959805981598259835984598559865987598859895990599159925993599459955996599759985999600060016002600360046005600660076008600960106011601260136014
  1. // ==++==
  2. //
  3. // Copyright (c) Microsoft Corporation. All rights reserved.
  4. //
  5. // ==--==
  6. // =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
  7. //
  8. // ParallelEnumerable.cs
  9. //
  10. // <OWNER>[....]</OWNER>
  11. //
  12. // The standard IEnumerable-based LINQ-to-Objects query provider. This class basically
  13. // mirrors the System.Linq.Enumerable class, but (1) takes as input a special "parallel
  14. // enumerable" data type and (2) uses an alternative implementation of the operators.
  15. //
  16. // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  17. using System;
  18. using System.Collections.Generic;
  19. using System.Threading;
  20. using System.Diagnostics.Contracts;
  21. using System.Linq.Parallel;
  22. using System.Collections.Concurrent;
  23. using System.Collections;
  24. using System.Threading.Tasks;
  25. #if SILVERLIGHT
  26. using System.Core; // for System.Core.SR
  27. #endif
  28. namespace System.Linq
  29. {
  30. //-----------------------------------------------------------------------------------
  31. // Languages like C# and VB that support query comprehensions translate queries
  32. // into calls to a query provider which creates executable representations of the
  33. // query. The LINQ-to-Objects provider is implemented as a static class with an
  34. // extension method per-query operator; when invoked, these return enumerable
  35. // objects that implement the querying behavior.
  36. //
  37. // We have a new sequence class for two reasons:
  38. //
  39. // (1) Developers can opt in to parallel query execution piecemeal, by using
  40. // a special AsParallel API to wrap the data source.
  41. // (2) Parallel LINQ uses a new representation for queries when compared to LINQ,
  42. // which we must return from the new sequence operator implementations.
  43. //
  44. // Comments and documentation will be somewhat light in this file. Please refer
  45. // to the "official" Standard Query Operators specification for details on each API:
  46. // http://download.microsoft.com/download/5/8/6/5868081c-68aa-40de-9a45-a3803d8134b8/Standard_Query_Operators.doc
  47. //
  48. // Notes:
  49. // The Standard Query Operators herein should be semantically equivalent to
  50. // the specification linked to above. In some cases, we offer operators that
  51. // aren't available in the sequential LINQ library; in each case, we will note
  52. // why this is needed.
  53. //
  54. /// <summary>
  55. /// Provides a set of methods for querying objects that implement
  56. /// ParallelQuery{TSource}. This is the parallel equivalent of
  57. /// <see cref="System.Linq.Enumerable"/>.
  58. /// </summary>
  59. public static class ParallelEnumerable
  60. {
  61. // We pass this string constant to an attribute constructor. Unfortunately, we cannot access resources from
  62. // an attribute constructor, so we have to store this string in source code.
  63. private const string RIGHT_SOURCE_NOT_PARALLEL_STR =
  64. "The second data source of a binary operator must be of type System.Linq.ParallelQuery<T> rather than "
  65. + "System.Collections.Generic.IEnumerable<T>. To fix this problem, use the AsParallel() extension method "
  66. + "to convert the right data source to System.Linq.ParallelQuery<T>.";
  67. //-----------------------------------------------------------------------------------
  68. // Converts any IEnumerable<TSource> into something that can be the target of parallel
  69. // query execution.
  70. //
  71. // Arguments:
  72. // source - the enumerable data source
  73. // options - query analysis options to override the defaults
  74. // degreeOfParallelism - the DOP to use instead of the system default, if any
  75. //
  76. // Notes:
  77. // If the argument is already a parallel enumerable, such as a query operator,
  78. // no new objects are allocated. Otherwise, a very simple wrapper is instantiated
  79. // that exposes the IEnumerable as a ParallelQuery.
  80. //
  81. /// <summary>
  82. /// Enables parallelization of a query.
  83. /// </summary>
  84. /// <typeparam name="TSource">The type of elements of <paramref name="source"/>.</typeparam>
  85. /// <param name="source">An <see cref="System.Collections.Generic.IEnumerable{T}"/>
  86. /// to convert to a <see cref="System.Linq.ParallelQuery{T}"/>.</param>
  87. /// <returns>The source as a <see cref="System.Linq.ParallelQuery{T}"/> to bind to
  88. /// ParallelEnumerable extension methods.</returns>
  89. /// <exception cref="T:System.ArgumentNullException">
  90. /// <paramref name="source"/> is a null reference (Nothing in Visual Basic).
  91. /// </exception>
  92. public static ParallelQuery<TSource> AsParallel<TSource>(this IEnumerable<TSource> source)
  93. {
  94. if (source == null)
  95. {
  96. throw new ArgumentNullException("source");
  97. }
  98. return new ParallelEnumerableWrapper<TSource>(source);
  99. }
  100. /// <summary>
  101. /// Enables parallelization of a query, as sourced by a partitioner
  102. /// responsible for splitting the input sequence into partitions.
  103. /// </summary>
  104. /// <typeparam name="TSource">The type of elements of <paramref name="source"/>.</typeparam>
  105. /// <param name="source">A partitioner over the input sequence.</param>
  106. /// <returns>The <paramref name="source"/> as a ParallelQuery to bind to ParallelEnumerable extension methods.</returns>
  107. /// <remarks>
  108. /// The source partitioner's GetOrderedPartitions method is used when ordering is enabled,
  109. /// whereas the partitioner's GetPartitions is used if ordering is not enabled (the default).
  110. /// The source partitioner's GetDynamicPartitions and GetDynamicOrderedPartitions are not used.
  111. /// </remarks>
  112. /// <exception cref="T:System.ArgumentNullException">
  113. /// <paramref name="source"/> is a null reference (Nothing in Visual Basic).
  114. /// </exception>
  115. public static ParallelQuery<TSource> AsParallel<TSource>(this Partitioner<TSource> source)
  116. {
  117. if (source == null)
  118. {
  119. throw new ArgumentNullException("source");
  120. }
  121. return new PartitionerQueryOperator<TSource>(source);
  122. }
  123. /// <summary>
  124. /// Enables treatment of a data source as if it was ordered, overriding the default of unordered.
  125. /// AsOrdered may only be invoked on sequences returned by AsParallel, ParallelEnumerable.Range,
  126. /// and ParallelEnumerable.Repeat.
  127. /// </summary>
  128. /// <typeparam name="TSource">The type of elements of <paramref name="source"/>.</typeparam>
  129. /// <param name="source">The input sequence.</param>
  130. /// <exception cref="T:System.InvalidOperationException">
  131. /// Thrown if <paramref name="source"/> is not one of AsParallel, ParallelEnumerable.Range, or ParallelEnumerable.Repeat.
  132. /// </exception>
  133. /// <exception cref="T:System.ArgumentNullException">
  134. /// <paramref name="source"/> is a null reference (Nothing in Visual Basic).
  135. /// </exception>
  136. /// <remarks>
  137. /// A natural tension exists between performance and preserving order in parallel processing. By default,
  138. /// a parallelized query behaves as if the ordering of the results is arbitrary
  139. /// unless AsOrdered is applied or there is an explicit OrderBy operator in the query.
  140. /// </remarks>
  141. /// <returns>The source sequence which will maintain ordering in the query.</returns>
  142. public static ParallelQuery<TSource> AsOrdered<TSource>(this ParallelQuery<TSource> source)
  143. {
  144. if (source == null)
  145. {
  146. throw new ArgumentNullException("source");
  147. }
  148. if (!(source is ParallelEnumerableWrapper<TSource> || source is IParallelPartitionable<TSource>))
  149. {
  150. PartitionerQueryOperator<TSource> partitionerOp = source as PartitionerQueryOperator<TSource>;
  151. if (partitionerOp != null)
  152. {
  153. if (!partitionerOp.Orderable)
  154. {
  155. throw new InvalidOperationException(SR.GetString(SR.ParallelQuery_PartitionerNotOrderable));
  156. }
  157. }
  158. else
  159. {
  160. throw new InvalidOperationException(SR.GetString(SR.ParallelQuery_InvalidAsOrderedCall));
  161. }
  162. }
  163. return new OrderingQueryOperator<TSource>(QueryOperator<TSource>.AsQueryOperator(source), true);
  164. }
  165. /// <summary>
  166. /// Enables treatment of a data source as if it was ordered, overriding the default of unordered.
  167. /// AsOrdered may only be invoked on sequences returned by AsParallel, ParallelEnumerable.Range,
  168. /// and ParallelEnumerable.Repeat.
  169. /// </summary>
  170. /// <param name="source">The input sequence.</param>
  171. /// <exception cref="InvalidOperationException">
  172. /// Thrown if the <paramref name="source"/> is not one of AsParallel, ParallelEnumerable.Range, or ParallelEnumerable.Repeat.
  173. /// </exception>
  174. /// <exception cref="T:System.ArgumentNullException">
  175. /// <paramref name="source"/> is a null reference (Nothing in Visual Basic).
  176. /// </exception>
  177. /// <remarks>
  178. /// A natural tension exists between performance and preserving order in parallel processing. By default,
  179. /// a parallelized query behaves as if the ordering of the results is arbitrary unless AsOrdered
  180. /// is applied or there is an explicit OrderBy operator in the query.
  181. /// </remarks>
  182. /// <returns>The source sequence which will maintain ordering in the query.</returns>
  183. public static ParallelQuery AsOrdered(this ParallelQuery source)
  184. {
  185. if (source == null)
  186. {
  187. throw new ArgumentNullException("source");
  188. }
  189. ParallelEnumerableWrapper wrapper = source as ParallelEnumerableWrapper;
  190. if (wrapper == null)
  191. {
  192. throw new InvalidOperationException(SR.GetString(SR.ParallelQuery_InvalidNonGenericAsOrderedCall));
  193. }
  194. return new OrderingQueryOperator<object>(QueryOperator<object>.AsQueryOperator(wrapper), true);
  195. }
  196. /// <summary>
  197. /// Allows an intermediate query to be treated as if no ordering is implied among the elements.
  198. /// </summary>
  199. /// <remarks>
  200. /// AsUnordered may provide
  201. /// performance benefits when ordering is not required in a portion of a query.
  202. /// </remarks>
  203. /// <typeparam name="TSource">The type of elements of <paramref name="source"/>.</typeparam>
  204. /// <param name="source">The input sequence.</param>
  205. /// <returns>The source sequence with arbitrary order.</returns>
  206. /// <exception cref="T:System.ArgumentNullException">
  207. /// <paramref name="source"/> is a null reference (Nothing in Visual Basic).
  208. /// </exception>
  209. public static ParallelQuery<TSource> AsUnordered<TSource>(this ParallelQuery<TSource> source)
  210. {
  211. if (source == null)
  212. {
  213. throw new ArgumentNullException("source");
  214. }
  215. return new OrderingQueryOperator<TSource>(QueryOperator<TSource>.AsQueryOperator(source), false);
  216. }
  217. /// <summary>
  218. /// Enables parallelization of a query.
  219. /// </summary>
  220. /// <param name="source">An <see cref="System.Collections.Generic.IEnumerable{T}"/> to convert
  221. /// to a <see cref="System.Linq.ParallelQuery{T}"/>.</param>
  222. /// <returns>
  223. /// The source as a ParallelQuery to bind to
  224. /// ParallelEnumerable extension methods.
  225. /// </returns>
  226. /// <exception cref="T:System.ArgumentNullException">
  227. /// <paramref name="source"/> is a null reference (Nothing in Visual Basic).
  228. /// </exception>
  229. public static ParallelQuery AsParallel(this IEnumerable source)
  230. {
  231. if (source == null) throw new ArgumentNullException("source");
  232. return new ParallelEnumerableWrapper(source);
  233. }
  234. //-----------------------------------------------------------------------------------
  235. // Converts a parallel enumerable into something that forces sequential execution.
  236. //
  237. // Arguments:
  238. // source - the parallel enumerable data source
  239. //
  240. /// <summary>
  241. /// Converts a <see cref="ParallelQuery{T}"/> into an
  242. /// <see cref="System.Collections.Generic.IEnumerable{T}"/> to force sequential
  243. /// evaluation of the query.
  244. /// </summary>
  245. /// <typeparam name="TSource">The type of elements of <paramref name="source"/>.</typeparam>
  246. /// <param name="source">A <see cref="ParallelQuery{T}"/> to convert to an <see cref="System.Collections.Generic.IEnumerable{T}"/>.</param>
  247. /// <returns>The source as an <see cref="System.Collections.Generic.IEnumerable{T}"/>
  248. /// to bind to sequential extension methods.</returns>
  249. /// <exception cref="T:System.ArgumentNullException">
  250. /// <paramref name="source"/> is a null reference (Nothing in Visual Basic).
  251. /// </exception>
  252. public static IEnumerable<TSource> AsSequential<TSource>(this ParallelQuery<TSource> source)
  253. {
  254. if (source == null) throw new ArgumentNullException("source");
  255. // Ditch the wrapper, if there is one.
  256. ParallelEnumerableWrapper<TSource> wrapper = source as ParallelEnumerableWrapper<TSource>;
  257. if (wrapper != null)
  258. {
  259. return wrapper.WrappedEnumerable;
  260. }
  261. else
  262. {
  263. return source;
  264. }
  265. }
  266. /// <summary>
  267. /// Sets the task scheduler to execute the query.
  268. /// </summary>
  269. /// <typeparam name="TSource">The type of elements of <paramref name="source"/>.</typeparam>
  270. /// <param name="source">A ParallelQuery on which to set the task scheduler option.</param>
  271. /// <param name="taskScheduler">Task scheduler to execute the query.</param>
  272. /// <returns>ParallelQuery representing the same query as source, but with the task scheduler option set.</returns>
  273. /// <exception cref="T:System.ArgumentNullException">
  274. /// <paramref name="source"/> or <paramref name="taskScheduler"/> is a null reference (Nothing in Visual Basic).
  275. /// </exception>
  276. /// <exception cref="T:System.InvalidOperationException">
  277. /// WithTaskScheduler is used multiple times in the query.
  278. /// </exception>
  279. internal static ParallelQuery<TSource> WithTaskScheduler<TSource>(this ParallelQuery<TSource> source, TaskScheduler taskScheduler)
  280. {
  281. if (source == null) throw new ArgumentNullException("source");
  282. if (taskScheduler == null) throw new ArgumentNullException("taskScheduler");
  283. QuerySettings settings = QuerySettings.Empty;
  284. settings.TaskScheduler = taskScheduler;
  285. return new QueryExecutionOption<TSource>(
  286. QueryOperator<TSource>.AsQueryOperator(source), settings);
  287. }
  288. /// <summary>
  289. /// Sets the degree of parallelism to use in a query. Degree of parallelism is the maximum number of concurrently
  290. /// executing tasks that will be used to process the query.
  291. /// </summary>
  292. /// <typeparam name="TSource">The type of elements of <paramref name="source"/>.</typeparam>
  293. /// <param name="source">A ParallelQuery on which to set the limit on the degrees of parallelism.</param>
  294. /// <param name="degreeOfParallelism">The degree of parallelism for the query.</param>
  295. /// <returns>ParallelQuery representing the same query as source, with the limit on the degrees of parallelism set.</returns>
  296. /// <exception cref="T:System.ArgumentNullException">
  297. /// <paramref name="source"/> is a null reference (Nothing in Visual Basic).
  298. /// </exception>
  299. /// <exception cref="T:System.InvalidOperationException">
  300. /// WithDegreeOfParallelism is used multiple times in the query.
  301. /// </exception>
  302. /// <exception cref="T:System.ArgumentOutOfRangeException">
  303. /// <paramref name="degreeOfParallelism"/> is less than 1 or greater than 512.
  304. /// </exception>
  305. public static ParallelQuery<TSource> WithDegreeOfParallelism<TSource>(this ParallelQuery<TSource> source, int degreeOfParallelism)
  306. {
  307. if (source == null) throw new ArgumentNullException("source");
  308. if (degreeOfParallelism < 1 || degreeOfParallelism > Scheduling.MAX_SUPPORTED_DOP)
  309. {
  310. throw new ArgumentOutOfRangeException("degreeOfParallelism");
  311. }
  312. QuerySettings settings = QuerySettings.Empty;
  313. settings.DegreeOfParallelism = degreeOfParallelism;
  314. return new QueryExecutionOption<TSource>(
  315. QueryOperator<TSource>.AsQueryOperator(source), settings);
  316. }
  317. /// <summary>
  318. /// Sets the <see cref="System.Threading.CancellationToken"/> to associate with the query.
  319. /// </summary>
  320. /// <typeparam name="TSource">The type of elements of <paramref name="source"/>.</typeparam>
  321. /// <param name="source">A ParallelQuery on which to set the option.</param>
  322. /// <param name="cancellationToken">A cancellation token.</param>
  323. /// <returns>ParallelQuery representing the same query as source, but with the <seealso cref="System.Threading.CancellationToken"/>
  324. /// registered.</returns>
  325. /// <exception cref="T:System.ArgumentNullException">
  326. /// <paramref name="source"/> is a null reference (Nothing in Visual Basic).
  327. /// </exception>
  328. /// <exception cref="T:System.InvalidOperationException">
  329. /// WithCancellation is used multiple times in the query.
  330. /// </exception>
  331. /// <exception cref="T:System.ObjectDisposedException">
  332. /// The <see cref="T:System.Threading.CancellationTokenSource"/> associated with the <paramref name="cancellationToken"/> has been disposed.
  333. /// </exception>
  334. public static ParallelQuery<TSource> WithCancellation<TSource>(this ParallelQuery<TSource> source, CancellationToken cancellationToken)
  335. {
  336. if (source == null) throw new ArgumentNullException("source");
  337. // also a convenience check whether the cancellationTokenSource backing the token is already disposed.
  338. // do this via a dummy registration as there is no public IsDipsosed property on CT.
  339. CancellationTokenRegistration dummyRegistration = new CancellationTokenRegistration();
  340. try
  341. {
  342. dummyRegistration = cancellationToken.Register(() => { });
  343. }
  344. catch (ObjectDisposedException)
  345. {
  346. throw new ArgumentException(SR.GetString(SR.ParallelEnumerable_WithCancellation_TokenSourceDisposed), "cancellationToken");
  347. }
  348. finally
  349. {
  350. dummyRegistration.Dispose();
  351. }
  352. QuerySettings settings = QuerySettings.Empty;
  353. settings.CancellationState = new CancellationState(cancellationToken);
  354. return new QueryExecutionOption<TSource>(
  355. QueryOperator<TSource>.AsQueryOperator(source), settings);
  356. }
  357. /// <summary>
  358. /// Sets the execution mode of the query.
  359. /// </summary>
  360. /// <typeparam name="TSource">The type of elements of <paramref name="source"/>.</typeparam>
  361. /// <param name="source">A ParallelQuery on which to set the option.</param>
  362. /// <param name="executionMode">The mode in which to execute the query.</param>
  363. /// <returns>ParallelQuery representing the same query as source, but with the
  364. /// <seealso cref="System.Linq.ParallelExecutionMode"/> registered.</returns>
  365. /// <exception cref="T:System.ArgumentNullException">
  366. /// <paramref name="source"/> is a null reference (Nothing in Visual Basic).
  367. /// </exception>
  368. /// <exception cref="T:System.ArgumentException">
  369. /// <paramref name="executionMode"/> is not a valid <see cref="T:System.Linq.ParallelExecutionMode"/> value.
  370. /// </exception>
  371. /// <exception cref="T:System.InvalidOperationException">
  372. /// WithExecutionMode is used multiple times in the query.
  373. /// </exception>
  374. public static ParallelQuery<TSource> WithExecutionMode<TSource>(this ParallelQuery<TSource> source, ParallelExecutionMode executionMode)
  375. {
  376. if (source == null) throw new ArgumentNullException("source");
  377. if (executionMode != ParallelExecutionMode.Default && executionMode != ParallelExecutionMode.ForceParallelism)
  378. {
  379. throw new ArgumentException(SR.GetString(SR.ParallelEnumerable_WithQueryExecutionMode_InvalidMode));
  380. }
  381. QuerySettings settings = QuerySettings.Empty;
  382. settings.ExecutionMode = executionMode;
  383. return new QueryExecutionOption<TSource>(
  384. QueryOperator<TSource>.AsQueryOperator(source), settings);
  385. }
  386. /// <summary>
  387. /// Sets the merge options for this query, which specify how the query will buffer output.
  388. /// </summary>
  389. /// <typeparam name="TSource">The type of elements of <paramref name="source"/>.</typeparam>
  390. /// <param name="source">A ParallelQuery on which to set the option.</param>
  391. /// <param name="mergeOptions">The merge optiosn to set for this query.</param>
  392. /// <returns>ParallelQuery representing the same query as source, but with the
  393. /// <seealso cref="ParallelMergeOptions"/> registered.</returns>
  394. /// <exception cref="T:System.ArgumentNullException">
  395. /// <paramref name="source"/> is a null reference (Nothing in Visual Basic).
  396. /// </exception>
  397. /// <exception cref="T:System.ArgumentException">
  398. /// <paramref name="mergeOptions"/> is not a valid <see cref="T:System.Linq.ParallelMergeOptions"/> value.
  399. /// </exception>
  400. /// <exception cref="T:System.InvalidOperationException">
  401. /// WithMergeOptions is used multiple times in the query.
  402. /// </exception>
  403. public static ParallelQuery<TSource> WithMergeOptions<TSource>(this ParallelQuery<TSource> source, ParallelMergeOptions mergeOptions)
  404. {
  405. if (source == null) throw new ArgumentNullException("source");
  406. if (mergeOptions != ParallelMergeOptions.Default
  407. && mergeOptions != ParallelMergeOptions.AutoBuffered
  408. && mergeOptions != ParallelMergeOptions.NotBuffered
  409. && mergeOptions != ParallelMergeOptions.FullyBuffered)
  410. {
  411. throw new ArgumentException(SR.GetString(SR.ParallelEnumerable_WithMergeOptions_InvalidOptions));
  412. }
  413. QuerySettings settings = QuerySettings.Empty;
  414. settings.MergeOptions = mergeOptions;
  415. return new QueryExecutionOption<TSource>(
  416. QueryOperator<TSource>.AsQueryOperator(source), settings);
  417. }
  418. //-----------------------------------------------------------------------------------
  419. // Range generates a sequence of numbers that can be used as input to a query.
  420. //
  421. /// <summary>
  422. /// Generates a parallel sequence of integral numbers within a specified range.
  423. /// </summary>
  424. /// <param name="start">The value of the first integer in the sequence.</param>
  425. /// <param name="count">The number of sequential integers to generate.</param>
  426. /// <returns>An <b>IEnumerable&lt;Int32&gt;</b> in C# or <B>IEnumerable(Of Int32)</B> in
  427. /// Visual Basic that contains a range of sequential integral numbers.</returns>
  428. /// <exception cref="T:System.ArgumentOutOfRangeException">
  429. /// <paramref name="count"/> is less than 0
  430. /// -or-
  431. /// <paramref name="start"/> + <paramref name="count"/> - 1 is larger than <see cref="M:System.Int32.MaxValue"/>.
  432. /// </exception>
  433. public static ParallelQuery<int> Range(int start, int count)
  434. {
  435. if (count < 0 || (count > 0 && Int32.MaxValue - (count - 1) < start)) throw new ArgumentOutOfRangeException("count");
  436. return new RangeEnumerable(start, count);
  437. }
  438. //-----------------------------------------------------------------------------------
  439. // Repeat just generates a sequence of size 'count' containing 'element'.
  440. //
  441. /// <summary>
  442. /// Generates a parallel sequence that contains one repeated value.
  443. /// </summary>
  444. /// <typeparam name="TResult">The type of the value to be repeated in the result sequence.</typeparam>
  445. /// <param name="element">The value to be repeated.</param>
  446. /// <param name="count">The number of times to repeat the value in the generated sequence.</param>
  447. /// <returns>A sequence that contains a repeated value.</returns>
  448. /// <exception cref="T:System.ArgumentOutOfRangeException">
  449. /// <paramref name="count"/> is less than 0.
  450. /// </exception>
  451. public static ParallelQuery<TResult> Repeat<TResult>(TResult element, int count)
  452. {
  453. if (count < 0) throw new ArgumentOutOfRangeException("count");
  454. return new RepeatEnumerable<TResult>(element, count);
  455. }
  456. //-----------------------------------------------------------------------------------
  457. // Returns an always-empty sequence.
  458. //
  459. /// <summary>
  460. /// Returns an empty ParallelQuery{TResult} that has the specified type argument.
  461. /// </summary>
  462. /// <typeparam name="TResult">The type to assign to the type parameter of the returned
  463. /// generic sequence.</typeparam>
  464. /// <returns>An empty sequence whose type argument is <typeparamref name="TResult"/>.</returns>
  465. public static ParallelQuery<TResult> Empty<TResult>()
  466. {
  467. return System.Linq.Parallel.EmptyEnumerable<TResult>.Instance;
  468. }
  469. //-----------------------------------------------------------------------------------
  470. // A new query operator that allows an arbitrary user-specified "action" to be
  471. // tacked on to the query tree. The action will be invoked for every element in the
  472. // underlying data source, avoiding a costly final merge in the query's execution,
  473. // which can lead to much better scalability. The caveat is that these occur in
  474. // parallel, so the user providing an action must take care to eliminate shared state
  475. // accesses or to synchronize as appropriate.
  476. //
  477. // Arguments:
  478. // source - the data source over which the actions will be invoked
  479. // action - a delegate representing the per-element action to be invoked
  480. //
  481. // Notes:
  482. // Neither source nor action may be null, otherwise this method throws.
  483. //
  484. /// <summary>
  485. /// Invokes in parallel the specified action for each element in the <paramref name="source"/>.
  486. /// </summary>
  487. /// <remarks>
  488. /// This is an efficient way to process the output from a parallelized query because it does
  489. /// not require a merge step at the end. However, order of execution is non-deterministic.
  490. /// </remarks>
  491. /// <typeparam name="TSource">The type of elements of <paramref name="source"/>.</typeparam>
  492. /// <param name="source">The <see cref="ParallelQuery{T}"/> whose elements will be processed by
  493. /// <paramref name="action"/>.</param>
  494. /// <param name="action">An Action to invoke on each element.</param>
  495. /// <exception cref="T:System.ArgumentNullException">
  496. /// <paramref name="source"/> or <paramref name="action"/> is a null reference (Nothing in Visual Basic).
  497. /// </exception>
  498. /// <exception cref="T:System.AggregateException">
  499. /// One or more exceptions occurred during the evaluation of the query.
  500. /// </exception>
  501. /// <exception cref="T:System.OperationCanceledException">
  502. /// The query was canceled.
  503. /// </exception>
  504. public static void ForAll<TSource>(this ParallelQuery<TSource> source, Action<TSource> action)
  505. {
  506. if (source == null) throw new ArgumentNullException("source");
  507. if (action == null) throw new ArgumentNullException("action");
  508. // We just instantiate the forall operator and invoke it synchronously on this thread.
  509. // By the time it returns, the entire query has been executed and the actions run..
  510. new ForAllOperator<TSource>(source, action).RunSynchronously();
  511. }
  512. /*===================================================================================
  513. * BASIC OPERATORS
  514. *===================================================================================*/
  515. //-----------------------------------------------------------------------------------
  516. // Where is an operator that filters any elements from the data source for which the
  517. // user-supplied predictate returns false.
  518. //
  519. /// <summary>
  520. /// Filters in parallel a sequence of values based on a predicate.
  521. /// </summary>
  522. /// <typeparam name="TSource">The type of the elements of source.</typeparam>
  523. /// <param name="source">A sequence to filter.</param>
  524. /// <param name="predicate">A function to test each element for a condition.</param>
  525. /// <returns>A sequence that contains elements from the input sequence that satisfy
  526. /// the condition.</returns>
  527. /// <exception cref="T:System.ArgumentNullException">
  528. /// <paramref name="source"/> or <paramref name="predicate"/> is a null reference (Nothing in Visual Basic).
  529. /// </exception>
  530. public static ParallelQuery<TSource> Where<TSource>(this ParallelQuery<TSource> source, Func<TSource, bool> predicate)
  531. {
  532. if (source == null) throw new ArgumentNullException("source");
  533. if (predicate == null) throw new ArgumentNullException("predicate");
  534. return new WhereQueryOperator<TSource>(source, predicate);
  535. }
  536. /// <summary>
  537. /// Filters in parallel a sequence of values based on a predicate. Each element's index is used in the logic of the predicate function.
  538. /// </summary>
  539. /// <typeparam name="TSource">The type of the elements of source.</typeparam>
  540. /// <param name="source">A sequence to filter.</param>
  541. /// <param name="predicate">A function to test each element for a condition.</param>
  542. /// <returns>A sequence that contains elements from the input sequence that satisfy the condition.</returns>
  543. /// <exception cref="T:System.ArgumentNullException">
  544. /// <paramref name="source"/> or <paramref name="predicate"/> is a null reference (Nothing in Visual Basic).
  545. /// </exception>
  546. public static ParallelQuery<TSource> Where<TSource>(this ParallelQuery<TSource> source, Func<TSource, int, bool> predicate)
  547. {
  548. if (source == null) throw new ArgumentNullException("source");
  549. if (predicate == null) throw new ArgumentNullException("predicate");
  550. return new IndexedWhereQueryOperator<TSource>(source, predicate);
  551. }
  552. //-----------------------------------------------------------------------------------
  553. // Select merely maps a selector delegate over each element in the data source.
  554. //
  555. /// <summary>
  556. /// Projects in parallel each element of a sequence into a new form.
  557. /// </summary>
  558. /// <typeparam name="TSource">The type of the elements of <paramref name="source"/>.</typeparam>
  559. /// <typeparam name="TResult">The type of elements resturned by <b>selector</b>.</typeparam>
  560. /// <param name="source">A sequence of values to invoke a transform function on.</param>
  561. /// <param name="selector">A transform function to apply to each element.</param>
  562. /// <returns>A sequence whose elements are the result of invoking the transform function on each
  563. /// element of <paramref name="source"/>.</returns>
  564. /// <exception cref="T:System.ArgumentNullException">
  565. /// <paramref name="source"/> or <paramref name="selector"/> is a null reference (Nothing in Visual Basic).
  566. /// </exception>
  567. public static ParallelQuery<TResult> Select<TSource, TResult>(
  568. this ParallelQuery<TSource> source, Func<TSource, TResult> selector)
  569. {
  570. if (source == null) throw new ArgumentNullException("source");
  571. if (selector == null) throw new ArgumentNullException("selector");
  572. return new SelectQueryOperator<TSource, TResult>(source, selector);
  573. }
  574. /// <summary>
  575. /// Projects in parallel each element of a sequence into a new form by incorporating the element's index.
  576. /// </summary>
  577. /// <typeparam name="TSource">The type of the elements of <paramref name="source"/>.</typeparam>
  578. /// <typeparam name="TResult">The type of elements resturned by <b>selector</b>.</typeparam>
  579. /// <param name="source">A sequence of values to invoke a transform function on.</param>
  580. /// <param name="selector">A transform function to apply to each element.</param>
  581. /// <returns>A sequence whose elements are the result of invoking the transform function on each
  582. /// element of <paramref name="source"/>.</returns>
  583. /// <exception cref="T:System.ArgumentNullException">
  584. /// <paramref name="source"/> or <paramref name="selector"/> is a null reference (Nothing in Visual Basic).
  585. /// </exception>
  586. public static ParallelQuery<TResult> Select<TSource, TResult>(
  587. this ParallelQuery<TSource> source, Func<TSource, int, TResult> selector)
  588. {
  589. if (source == null) throw new ArgumentNullException("source");
  590. if (selector == null) throw new ArgumentNullException("selector");
  591. return new IndexedSelectQueryOperator<TSource, TResult>(source, selector);
  592. }
  593. //-----------------------------------------------------------------------------------
  594. // Zip combines an outer and inner data source into a single output data stream.
  595. //
  596. /// <summary>
  597. /// Merges in parallel two sequences by using the specified predicate function.
  598. /// </summary>
  599. /// <typeparam name="TFirst">The type of the elements of the first sequence.</typeparam>
  600. /// <typeparam name="TSecond">The type of the elements of the second sequence.</typeparam>
  601. /// <typeparam name="TResult">The type of the return elements.</typeparam>
  602. /// <param name="first">The first sequence to zip.</param>
  603. /// <param name="second">The second sequence to zip.</param>
  604. /// <param name="resultSelector">A function to create a result element from two matching elements.</param>
  605. /// <returns>
  606. /// A sequence that has elements of type <typeparamref name="TResult"/> that are obtained by performing
  607. /// resultSelector pairwise on two sequences. If the sequence lengths are unequal, this truncates
  608. /// to the length of the shorter sequence.
  609. /// </returns>
  610. /// <exception cref="T:System.ArgumentNullException">
  611. /// <paramref name="first"/> or <paramref name="second"/> or <paramref name="resultSelector"/> is a null reference (Nothing in Visual Basic).
  612. /// </exception>
  613. public static ParallelQuery<TResult> Zip<TFirst, TSecond, TResult>(
  614. this ParallelQuery<TFirst> first, ParallelQuery<TSecond> second, Func<TFirst, TSecond, TResult> resultSelector)
  615. {
  616. if (first == null) throw new ArgumentNullException("first");
  617. if (second == null) throw new ArgumentNullException("second");
  618. if (resultSelector == null) throw new ArgumentNullException("resultSelector");
  619. return new ZipQueryOperator<TFirst, TSecond, TResult>(first, second, resultSelector);
  620. }
  621. /// <summary>
  622. /// This Zip overload should never be called.
  623. /// This method is marked as obsolete and always throws
  624. /// <see cref="System.NotSupportedException"/> when invoked.
  625. /// </summary>
  626. /// <typeparam name="TFirst">This type parameter is not used.</typeparam>
  627. /// <typeparam name="TSecond">This type parameter is not used.</typeparam>
  628. /// <typeparam name="TResult">This type parameter is not used.</typeparam>
  629. /// <param name="first">This parameter is not used.</param>
  630. /// <param name="second">This parameter is not used.</param>
  631. /// <param name="resultSelector">This parameter is not used.</param>
  632. /// <returns>This overload always throws a <see cref="System.NotSupportedException"/>.</returns>
  633. /// <exception cref="T:System.NotSupportedException">The exception that occurs when this method is called.</exception>
  634. /// <remarks>
  635. /// This overload exists to disallow usage of Zip with a left data source of type
  636. /// <see cref="System.Linq.ParallelQuery{TFirst}"/> and a right data source of type <see cref="System.Collections.Generic.IEnumerable{TSecond}"/>.
  637. /// Otherwise, the Zip operator would appear to be bind to the parallel implementation, but would in reality bind to the sequential implementation.
  638. /// </remarks>
  639. [Obsolete(RIGHT_SOURCE_NOT_PARALLEL_STR)]
  640. public static ParallelQuery<TResult> Zip<TFirst, TSecond, TResult>(
  641. this ParallelQuery<TFirst> first, IEnumerable<TSecond> second, Func<TFirst, TSecond, TResult> resultSelector)
  642. {
  643. throw new NotSupportedException(SR.GetString(SR.ParallelEnumerable_BinaryOpMustUseAsParallel));
  644. }
  645. //-----------------------------------------------------------------------------------
  646. // Join is an inner join operator, i.e. elements from outer with no inner matches
  647. // will yield no results in the output data stream.
  648. //
  649. /// <summary>
  650. /// Correlates in parallel the elements of two sequences based on matching keys.
  651. /// The default equality comparer is used to compare keys.
  652. /// </summary>
  653. /// <typeparam name="TOuter">The type of the elements of the first sequence.</typeparam>
  654. /// <typeparam name="TInner">The type of the elements of the second sequence.</typeparam>
  655. /// <typeparam name="TKey">The type of the keys returned by the key selector functions.</typeparam>
  656. /// <typeparam name="TResult">The type of the result elements.</typeparam>
  657. /// <param name="outer">The first sequence to join.</param>
  658. /// <param name="inner">The sequence to join to the first sequence.</param>
  659. /// <param name="outerKeySelector">A function to extract the join key from each element of
  660. /// the first sequence.</param>
  661. /// <param name="innerKeySelector">A function to extract the join key from each element of
  662. /// the second sequence.</param>
  663. /// <param name="resultSelector">A function to create a result element from two matching elements.</param>
  664. /// <returns>A sequence that has elements of type <typeparamref name="TResult"/> that are obtained by performing
  665. /// an inner join on two sequences.</returns>
  666. /// <exception cref="T:System.ArgumentNullException">
  667. /// <paramref name="outer"/> or <paramref name="inner"/> or <paramref name="outerKeySelector"/> or
  668. /// <paramref name="innerKeySelector"/> or <paramref name="resultSelector"/> is a null reference (Nothing in Visual Basic).
  669. /// </exception>
  670. public static ParallelQuery<TResult> Join<TOuter, TInner, TKey, TResult>(
  671. this ParallelQuery<TOuter> outer, ParallelQuery<TInner> inner,
  672. Func<TOuter, TKey> outerKeySelector, Func<TInner, TKey> innerKeySelector,
  673. Func<TOuter, TInner, TResult> resultSelector)
  674. {
  675. return Join<TOuter, TInner, TKey, TResult>(
  676. outer, inner, outerKeySelector, innerKeySelector, resultSelector, null);
  677. }
  678. /// <summary>
  679. /// This Join overload should never be called.
  680. /// This method is marked as obsolete and always throws <see cref="System.NotSupportedException"/> when invoked.
  681. /// </summary>
  682. /// <typeparam name="TOuter">This type parameter is not used.</typeparam>
  683. /// <typeparam name="TInner">This type parameter is not used.</typeparam>
  684. /// <typeparam name="TKey">This type parameter is not used.</typeparam>
  685. /// <typeparam name="TResult">This type parameter is not used.</typeparam>
  686. /// <param name="outer">This parameter is not used.</param>
  687. /// <param name="inner">This parameter is not used.</param>
  688. /// <param name="outerKeySelector">This parameter is not used.</param>
  689. /// <param name="innerKeySelector">This parameter is not used.</param>
  690. /// <param name="resultSelector">This parameter is not used.</param>
  691. /// <returns>This overload always throws a <see cref="System.NotSupportedException"/>.</returns>
  692. /// <exception cref="T:System.NotSupportedException">The exception that occurs when this method is called.</exception>
  693. /// <remarks>
  694. /// This overload exists to disallow usage Join with a left data source of type
  695. /// <see cref="System.Linq.ParallelQuery{TOuter}"/> and a right data source of type <see cref="System.Collections.Generic.IEnumerable{TInner}"/>.
  696. /// Otherwise, the Join operator would appear to be binding to the parallel implementation, but would in reality bind to the sequential implementation.
  697. /// </remarks>
  698. [Obsolete(RIGHT_SOURCE_NOT_PARALLEL_STR)]
  699. public static ParallelQuery<TResult> Join<TOuter, TInner, TKey, TResult>(
  700. this ParallelQuery<TOuter> outer, IEnumerable<TInner> inner,
  701. Func<TOuter, TKey> outerKeySelector, Func<TInner, TKey> innerKeySelector,
  702. Func<TOuter, TInner, TResult> resultSelector)
  703. {
  704. throw new NotSupportedException(SR.GetString(SR.ParallelEnumerable_BinaryOpMustUseAsParallel));
  705. }
  706. /// <summary>
  707. /// Correlates in parallel the elements of two sequences based on matching keys.
  708. /// A specified IEqualityComparer{T} is used to compare keys.
  709. /// </summary>
  710. /// <typeparam name="TOuter">The type of the elements of the first sequence.</typeparam>
  711. /// <typeparam name="TInner">The type of the elements of the second sequence.</typeparam>
  712. /// <typeparam name="TKey">The type of the keys returned by the key selector functions.</typeparam>
  713. /// <typeparam name="TResult">The type of the result elements.</typeparam>
  714. /// <param name="outer">The first sequence to join.</param>
  715. /// <param name="inner">The sequence to join to the first sequence.</param>
  716. /// <param name="outerKeySelector">A function to extract the join key from each element
  717. /// of the first sequence.</param>
  718. /// <param name="innerKeySelector">A function to extract the join key from each element
  719. /// of the second sequence.</param>
  720. /// <param name="resultSelector">A function to create a result element from two matching elements.</param>
  721. /// <param name="comparer">An IEqualityComparer&lt;(Of &lt;(T&gt;)&gt;) to hash and compare keys.</param>
  722. /// <returns>A sequence that has elements of type <typeparamref name="TResult"/> that are obtained by performing
  723. /// an inner join on two sequences.</returns>
  724. /// <exception cref="T:System.ArgumentNullException">
  725. /// <paramref name="outer"/> or <paramref name="inner"/> or <paramref name="outerKeySelector"/> or
  726. /// <paramref name="innerKeySelector"/> or <paramref name="resultSelector"/> is a null reference (Nothing in Visual Basic).
  727. /// </exception>
  728. public static ParallelQuery<TResult> Join<TOuter, TInner, TKey, TResult>(
  729. this ParallelQuery<TOuter> outer, ParallelQuery<TInner> inner,
  730. Func<TOuter, TKey> outerKeySelector, Func<TInner, TKey> innerKeySelector,
  731. Func<TOuter, TInner, TResult> resultSelector, IEqualityComparer<TKey> comparer)
  732. {
  733. if (outer == null) throw new ArgumentNullException("outer");
  734. if (inner == null) throw new ArgumentNullException("inner");
  735. if (outerKeySelector == null) throw new ArgumentNullException("outerKeySelector");
  736. if (innerKeySelector == null) throw new ArgumentNullException("innerKeySelector");
  737. if (resultSelector == null) throw new ArgumentNullException("resultSelector");
  738. return new JoinQueryOperator<TOuter, TInner, TKey, TResult>(
  739. outer, inner, outerKeySelector, innerKeySelector, resultSelector, comparer);
  740. }
  741. /// <summary>
  742. /// This Join overload should never be called.
  743. /// This method is marked as obsolete and always throws <see cref="System.NotSupportedException"/> when invoked.
  744. /// </summary>
  745. /// <typeparam name="TOuter">This type parameter is not used.</typeparam>
  746. /// <typeparam name="TInner">This type parameter is not used.</typeparam>
  747. /// <typeparam name="TKey">This type parameter is not used.</typeparam>
  748. /// <typeparam name="TResult">This type parameter is not used.</typeparam>
  749. /// <param name="outer">This parameter is not used.</param>
  750. /// <param name="inner">This parameter is not used.</param>
  751. /// <param name="outerKeySelector">This parameter is not used.</param>
  752. /// <param name="innerKeySelector">This parameter is not used.</param>
  753. /// <param name="resultSelector">This parameter is not used.</param>
  754. /// <param name="comparer">This parameter is not used.</param>
  755. /// <returns>This overload always throws a <see cref="System.NotSupportedException"/>.</returns>
  756. /// <exception cref="T:System.NotSupportedException">The exception that occurs when this method is called.</exception>
  757. /// <remarks>
  758. /// This overload exists to disallow usage of Join with a left data source of type
  759. /// <see cref="System.Linq.ParallelQuery{TOuter}"/> and a right data source of type <see cref="System.Collections.Generic.IEnumerable{TInner}"/>.
  760. /// Otherwise, the Join operator would appear to be binding to the parallel implementation, but would in reality bind to the sequential implementation.
  761. /// </remarks>
  762. [Obsolete(RIGHT_SOURCE_NOT_PARALLEL_STR)]
  763. public static ParallelQuery<TResult> Join<TOuter, TInner, TKey, TResult>(
  764. this ParallelQuery<TOuter> outer, IEnumerable<TInner> inner,
  765. Func<TOuter, TKey> outerKeySelector, Func<TInner, TKey> innerKeySelector,
  766. Func<TOuter, TInner, TResult> resultSelector, IEqualityComparer<TKey> comparer)
  767. {
  768. throw new NotSupportedException(SR.GetString(SR.ParallelEnumerable_BinaryOpMustUseAsParallel));
  769. }
  770. //-----------------------------------------------------------------------------------
  771. // GroupJoin is an outer join operator, i.e. elements from outer with no inner matches
  772. // will yield results (empty lists) in the output data stream.
  773. //
  774. /// <summary>
  775. /// Correlates in parallel the elements of two sequences based on equality of keys and groups the results.
  776. /// The default equality comparer is used to compare keys.
  777. /// </summary>
  778. /// <typeparam name="TOuter">The type of the elements of the first sequence.</typeparam>
  779. /// <typeparam name="TInner">The type of the elements of the second sequence.</typeparam>
  780. /// <typeparam name="TKey">The type of the keys returned by the key selector functions.</typeparam>
  781. /// <typeparam name="TResult">The type of the result elements.</typeparam>
  782. /// <param name="outer">The first sequence to join.</param>
  783. /// <param name="inner">The sequence to join to the first sequence.</param>
  784. /// <param name="outerKeySelector">A function to extract the join key from each element
  785. /// of the first sequence.</param>
  786. /// <param name="innerKeySelector">A function to extract the join key from each element
  787. /// of the second sequence.</param>
  788. /// <param name="resultSelector">A function to create a result element from an element from
  789. /// the first sequence and a collection of matching elements from the second sequence.</param>
  790. /// <returns>A sequence that has elements of type <typeparamref name="TResult"/> that are obtained by performing
  791. /// a grouped join on two sequences.</returns>
  792. /// <exception cref="T:System.ArgumentNullException">
  793. /// <paramref name="outer"/> or <paramref name="inner"/> or <paramref name="outerKeySelector"/> or
  794. /// <paramref name="innerKeySelector"/> or <paramref name="resultSelector"/> is a null reference (Nothing in Visual Basic).
  795. /// </exception>
  796. public static ParallelQuery<TResult> GroupJoin<TOuter, TInner, TKey, TResult>(
  797. this ParallelQuery<TOuter> outer, ParallelQuery<TInner> inner,
  798. Func<TOuter, TKey> outerKeySelector, Func<TInner, TKey> innerKeySelector,
  799. Func<TOuter, IEnumerable<TInner>, TResult> resultSelector)
  800. {
  801. return GroupJoin<TOuter, TInner, TKey, TResult>(
  802. outer, inner, outerKeySelector, innerKeySelector, resultSelector, null);
  803. }
  804. /// <summary>
  805. /// This GroupJoin overload should never be called.
  806. /// This method is marked as obsolete and always throws <see cref="System.NotSupportedException"/> when called.
  807. /// </summary>
  808. /// <typeparam name="TOuter">This type parameter is not used.</typeparam>
  809. /// <typeparam name="TInner">This type parameter is not used.</typeparam>
  810. /// <typeparam name="TKey">This type parameter is not used.</typeparam>
  811. /// <typeparam name="TResult">This type parameter is not used.</typeparam>
  812. /// <param name="outer">This parameter is not used.</param>
  813. /// <param name="inner">This parameter is not used.</param>
  814. /// <param name="outerKeySelector">This parameter is not used.</param>
  815. /// <param name="innerKeySelector">This parameter is not used.</param>
  816. /// <param name="resultSelector">This parameter is not used.</param>
  817. /// <returns>This overload always throws a <see cref="System.NotSupportedException"/>.</returns>
  818. /// <exception cref="T:System.NotSupportedException">The exception that occurs when this method is called.</exception>
  819. /// <remarks>
  820. /// This overload exists to disallow usage of GroupJoin with a left data source of type
  821. /// <see cref="System.Linq.ParallelQuery{TOuter}"/> and a right data source of type <see cref="System.Collections.Generic.IEnumerable{TInner}"/>.
  822. /// Otherwise, the GroupJoin operator would appear to be binding to the parallel implementation,
  823. /// but would in reality bind to the sequential implementation.
  824. ///</remarks>
  825. [Obsolete(RIGHT_SOURCE_NOT_PARALLEL_STR)]
  826. public static ParallelQuery<TResult> GroupJoin<TOuter, TInner, TKey, TResult>(
  827. this ParallelQuery<TOuter> outer, IEnumerable<TInner> inner,
  828. Func<TOuter, TKey> outerKeySelector, Func<TInner, TKey> innerKeySelector,
  829. Func<TOuter, IEnumerable<TInner>, TResult> resultSelector)
  830. {
  831. throw new NotSupportedException(SR.GetString(SR.ParallelEnumerable_BinaryOpMustUseAsParallel));
  832. }
  833. /// <summary>
  834. /// Correlates in parallel the elements of two sequences based on key equality and groups the results.
  835. /// A specified IEqualityComparer{T} is used to compare keys.
  836. /// </summary>
  837. /// <typeparam name="TOuter">The type of the elements of the first sequence.</typeparam>
  838. /// <typeparam name="TInner">The type of the elements of the second sequence.</typeparam>
  839. /// <typeparam name="TKey">The type of the keys returned by the key selector functions.</typeparam>
  840. /// <typeparam name="TResult">The type of the result elements.</typeparam>
  841. /// <param name="outer">The first sequence to join.</param>
  842. /// <param name="inner">The sequence to join to the first sequence.</param>
  843. /// <param name="outerKeySelector">A function to extract the join key from each element
  844. /// of the first sequence.</param>
  845. /// <param name="innerKeySelector">A function to extract the join key from each element
  846. /// of the second sequence.</param>
  847. /// <param name="resultSelector">A function to create a result element from an element from
  848. /// the first sequence and a collection of matching elements from the second sequence.</param>
  849. /// <param name="comparer">An IEqualityComparer&lt;(Of &lt;(T&gt;)&gt;) to hash and compare keys.</param>
  850. /// <returns>A sequence that has elements of type <typeparamref name="TResult"/> that are obtained by performing
  851. /// a grouped join on two sequences.</returns>
  852. /// <exception cref="T:System.ArgumentNullException">
  853. /// <paramref name="outer"/> or <paramref name="inner"/> or <paramref name="outerKeySelector"/> or
  854. /// <paramref name="innerKeySelector"/> or <paramref name="resultSelector"/> is a null reference (Nothing in Visual Basic).
  855. /// </exception>
  856. public static ParallelQuery<TResult> GroupJoin<TOuter, TInner, TKey, TResult>(
  857. this ParallelQuery<TOuter> outer, ParallelQuery<TInner> inner,
  858. Func<TOuter, TKey> outerKeySelector, Func<TInner, TKey> innerKeySelector,
  859. Func<TOuter, IEnumerable<TInner>, TResult> resultSelector, IEqualityComparer<TKey> comparer)
  860. {
  861. if (outer == null) throw new ArgumentNullException("outer");
  862. if (inner == null) throw new ArgumentNullException("inner");
  863. if (outerKeySelector == null) throw new ArgumentNullException("outerKeySelector");
  864. if (innerKeySelector == null) throw new ArgumentNullException("innerKeySelector");
  865. if (resultSelector == null) throw new ArgumentNullException("resultSelector");
  866. return new GroupJoinQueryOperator<TOuter, TInner, TKey, TResult>(outer, inner,
  867. outerKeySelector, innerKeySelector, resultSelector, comparer);
  868. }
  869. /// <summary>
  870. /// This GroupJoin overload should never be called.
  871. /// This method is marked as obsolete and always throws <see cref="System.NotSupportedException"/> when called.
  872. /// </summary>
  873. /// <typeparam name="TOuter">This type parameter is not used.</typeparam>
  874. /// <typeparam name="TInner">This type parameter is not used.</typeparam>
  875. /// <typeparam name="TKey">This type parameter is not used.</typeparam>
  876. /// <typeparam name="TResult">This type parameter is not used.</typeparam>
  877. /// <param name="outer">This parameter is not used.</param>
  878. /// <param name="inner">This parameter is not used.</param>
  879. /// <param name="outerKeySelector">This parameter is not used.</param>
  880. /// <param name="innerKeySelector">This parameter is not used.</param>
  881. /// <param name="resultSelector">This parameter is not used.</param>
  882. /// <param name="comparer">This parameter is not used.</param>
  883. /// <returns>This overload always throws a <see cref="System.NotSupportedException"/>.</returns>
  884. /// <exception cref="T:System.NotSupportedException">The exception that occurs when this method is called.</exception>
  885. /// <remarks>
  886. /// This overload exists to disallow usage of GroupJoin with a left data source of type
  887. /// <see cref="System.Linq.ParallelQuery{TOuter}"/> and a right data source of type <see cref="System.Collections.Generic.IEnumerable{TInner}"/>.
  888. /// Otherwise, the GroupJoin operator would appear to be binding to the parallel implementation,
  889. /// but would in reality bind to the sequential implementation.
  890. /// </remarks>
  891. [Obsolete(RIGHT_SOURCE_NOT_PARALLEL_STR)]
  892. public static ParallelQuery<TResult> GroupJoin<TOuter, TInner, TKey, TResult>(
  893. this ParallelQuery<TOuter> outer, IEnumerable<TInner> inner,
  894. Func<TOuter, TKey> outerKeySelector, Func<TInner, TKey> innerKeySelector,
  895. Func<TOuter, IEnumerable<TInner>, TResult> resultSelector, IEqualityComparer<TKey> comparer)
  896. {
  897. throw new NotSupportedException(SR.GetString(SR.ParallelEnumerable_BinaryOpMustUseAsParallel));
  898. }
  899. //-----------------------------------------------------------------------------------
  900. // SelectMany is a kind of nested loops join. For each element in the outer data
  901. // source, we enumerate each element in the inner data source, yielding the result
  902. // with some kind of selection routine. A few different flavors are supported.
  903. //
  904. /// <summary>
  905. /// Projects in parallel each element of a sequence to an IEnumerable{T}
  906. /// and flattens the resulting sequences into one sequence.
  907. /// </summary>
  908. /// <typeparam name="TSource">The type of elements of <paramref name="source"/>.</typeparam>
  909. /// <typeparam name="TResult">The type of the elements of the sequence returned by <B>selector</B>.</typeparam>
  910. /// <param name="source">A sequence of values to project.</param>
  911. /// <param name="selector">A transform function to apply to each element.</param>
  912. /// <returns>A sequence whose elements are the result of invoking the one-to-many transform
  913. /// function on each element of the input sequence.</returns>
  914. /// <exception cref="T:System.ArgumentNullException">
  915. /// <paramref name="source"/> or <paramref name="selector"/> is a null reference (Nothing in Visual Basic).
  916. /// </exception>
  917. public static ParallelQuery<TResult> SelectMany<TSource, TResult>(
  918. this ParallelQuery<TSource> source, Func<TSource, IEnumerable<TResult>> selector)
  919. {
  920. if (source == null) throw new ArgumentNullException("source");
  921. if (selector == null) throw new ArgumentNullException("selector");
  922. return new SelectManyQueryOperator<TSource, TResult, TResult>(source, selector, null, null);
  923. }
  924. /// <summary>
  925. /// Projects in parallel each element of a sequence to an IEnumerable{T}, and flattens the resulting
  926. /// sequences into one sequence. The index of each source element is used in the projected form of
  927. /// that element.
  928. /// </summary>
  929. /// <typeparam name="TSource">The type of elements of <paramref name="source"/>.</typeparam>
  930. /// <typeparam name="TResult">The type of the elements of the sequence returned by <B>selector</B>.</typeparam>
  931. /// <param name="source">A sequence of values to project.</param>
  932. /// <param name="selector">A transform function to apply to each element.</param>
  933. /// <returns>A sequence whose elements are the result of invoking the one-to-many transform
  934. /// function on each element of the input sequence.</returns>
  935. /// <exception cref="T:System.ArgumentNullException">
  936. /// <paramref name="source"/> or <paramref name="selector"/> is a null reference (Nothing in Visual Basic).
  937. /// </exception>
  938. public static ParallelQuery<TResult> SelectMany<TSource, TResult>(
  939. this ParallelQuery<TSource> source, Func<TSource, int, IEnumerable<TResult>> selector)
  940. {
  941. if (source == null) throw new ArgumentNullException("source");
  942. if (selector == null) throw new ArgumentNullException("selector");
  943. return new SelectManyQueryOperator<TSource, TResult, TResult>(source, null, selector, null);
  944. }
  945. /// <summary>
  946. /// Projects each element of a sequence to an IEnumerable{T},
  947. /// flattens the resulting sequences into one sequence, and invokes a result selector
  948. /// function on each element therein.
  949. /// </summary>
  950. /// <typeparam name="TSource">The type of elements of <paramref name="source"/>.</typeparam>
  951. /// <typeparam name="TCollection">The type of the intermediate elements collected by <paramref name="collectionSelector"/>.</typeparam>
  952. /// <typeparam name="TResult"></typeparam>
  953. /// <param name="source">A sequence of values to project.</param>
  954. /// <param name="collectionSelector">A transform function to apply to each source element;
  955. /// the second parameter of the function represents the index of the source element.</param>
  956. /// <param name="resultSelector">A function to create a result element from an element from
  957. /// the first sequence and a collection of matching elements from the second sequence.</param>
  958. /// <returns>A sequence whose elements are the result of invoking the one-to-many transform
  959. /// function <paramref name="collectionSelector"/> on each element of <paramref name="source"/> and then mapping
  960. /// each of those sequence elements and their corresponding source element to a result element.</returns>
  961. /// <exception cref="T:System.ArgumentNullException">
  962. /// <paramref name="source"/> or <paramref name="collectionSelector"/> or
  963. /// <paramref name="resultSelector"/> is a null reference (Nothing in Visual Basic).
  964. /// </exception>
  965. public static ParallelQuery<TResult> SelectMany<TSource, TCollection, TResult>(
  966. this ParallelQuery<TSource> source, Func<TSource, IEnumerable<TCollection>> collectionSelector,
  967. Func<TSource, TCollection, TResult> resultSelector)
  968. {
  969. if (source == null) throw new ArgumentNullException("source");
  970. if (collectionSelector == null) throw new ArgumentNullException("collectionSelector");
  971. if (resultSelector == null) throw new ArgumentNullException("resultSelector");
  972. return new SelectManyQueryOperator<TSource, TCollection, TResult>(source, collectionSelector, null, resultSelector);
  973. }
  974. /// <summary>
  975. /// Projects each element of a sequence to an IEnumerable{T}, flattens the resulting
  976. /// sequences into one sequence, and invokes a result selector function on each element
  977. /// therein. The index of each source element is used in the intermediate projected
  978. /// form of that element.
  979. /// </summary>
  980. /// <typeparam name="TSource">The type of elements of <paramref name="source"/>.</typeparam>
  981. /// <typeparam name="TCollection">The type of the intermediate elements collected by
  982. /// <paramref name="collectionSelector"/>.</typeparam>
  983. /// <typeparam name="TResult">The type of elements to return.</typeparam>
  984. /// <param name="source">A sequence of values to project.</param>
  985. /// <param name="collectionSelector">A transform function to apply to each source element;
  986. /// the second parameter of the function represents the index of the source element.</param>
  987. /// <param name="resultSelector">A function to create a result element from an element from
  988. /// the first sequence and a collection of matching elements from the second sequence.</param>
  989. /// <returns>
  990. /// A sequence whose elements are the result of invoking the one-to-many transform
  991. /// function <paramref name="collectionSelector"/> on each element of <paramref name="source"/> and then mapping
  992. /// each of those sequence elements and their corresponding source element to a
  993. /// result element.
  994. /// </returns>
  995. /// <exception cref="T:System.ArgumentNullException">
  996. /// <paramref name="source"/> or <paramref name="collectionSelector"/> or
  997. /// <paramref name="resultSelector"/> is a null reference (Nothing in Visual Basic).
  998. /// </exception>
  999. public static ParallelQuery<TResult> SelectMany<TSource, TCollection, TResult>(
  1000. this ParallelQuery<TSource> source, Func<TSource, int, IEnumerable<TCollection>> collectionSelector,
  1001. Func<TSource, TCollection, TResult> resultSelector)
  1002. {
  1003. if (source == null) throw new ArgumentNullException("source");
  1004. if (collectionSelector == null) throw new ArgumentNullException("collectionSelector");
  1005. if (resultSelector == null) throw new ArgumentNullException("resultSelector");
  1006. return new SelectManyQueryOperator<TSource, TCollection, TResult>(source, null, collectionSelector, resultSelector);
  1007. }
  1008. //-----------------------------------------------------------------------------------
  1009. // OrderBy and ThenBy establish an ordering among elements, using user-specified key
  1010. // selection and key comparison routines. There are also descending sort variants.
  1011. //
  1012. /// <summary>
  1013. /// Sorts in parallel the elements of a sequence in ascending order according to a key.
  1014. /// </summary>
  1015. /// <remarks>
  1016. /// In contrast to the sequential implementation, this is not a stable sort.
  1017. /// To achieve a stable sort, change a query of the form:
  1018. /// <code>var ordered = source.OrderBy((e) => e.k);</code>
  1019. /// to instead be formed as:
  1020. /// <code>var ordered = source.Select((e,i) => new { E=e, I=i }).OrderBy((v) => v.i).Select((v) => v.e);</code>
  1021. /// </remarks>
  1022. /// <typeparam name="TSource">The type of elements of <paramref name="source"/>.</typeparam>
  1023. /// <typeparam name="TKey">The type of the key returned by <paramref name="keySelector"/>.</typeparam>
  1024. /// <param name="source">A sequence of values to order.</param>
  1025. /// <param name="keySelector">A function to extract a key from an element.</param>
  1026. /// <returns>An OrderedParallelQuery{TSource} whose elements are sorted
  1027. /// according to a key.</returns>
  1028. /// <exception cref="T:System.ArgumentNullException">
  1029. /// <paramref name="source"/> or <paramref name="keySelector"/> is a null reference (Nothing in Visual Basic).
  1030. /// </exception>
  1031. public static OrderedParallelQuery<TSource> OrderBy<TSource, TKey>(
  1032. this ParallelQuery<TSource> source, Func<TSource, TKey> keySelector)
  1033. {
  1034. if (source == null) throw new ArgumentNullException("source");
  1035. if (keySelector == null) throw new ArgumentNullException("keySelector");
  1036. return new OrderedParallelQuery<TSource>(
  1037. new SortQueryOperator<TSource, TKey>(source, keySelector, null, false));
  1038. }
  1039. /// <summary>
  1040. /// Sorts in parallel the elements of a sequence in ascending order by using a specified comparer.
  1041. /// </summary>
  1042. /// <remarks>
  1043. /// In contrast to the sequential implementation, this is not a stable sort.
  1044. /// See the remarks for OrderBy(ParallelQuery{TSource}, Func{TSource,TKey}) for
  1045. /// an approach to implementing a stable sort.
  1046. /// </remarks>
  1047. /// <typeparam name="TSource">The type of elements of <paramref name="source"/>.</typeparam>
  1048. /// <typeparam name="TKey">The type of the key returned by <paramref name="keySelector"/>.</typeparam>
  1049. /// <param name="source">A sequence of values to order.</param>
  1050. /// <param name="keySelector">A function to extract a key from an element.</param>
  1051. /// <param name="comparer">An IComparer{TKey} to compare keys.</param>
  1052. /// <returns>An OrderedParallelQuery{TSource} whose elements are sorted according
  1053. /// to a key.</returns>
  1054. /// <exception cref="T:System.ArgumentNullException">
  1055. /// <paramref name="source"/> or <paramref name="keySelector"/> is a null reference (Nothing in Visual Basic).
  1056. /// </exception>
  1057. public static OrderedParallelQuery<TSource> OrderBy<TSource, TKey>(
  1058. this ParallelQuery<TSource> source, Func<TSource, TKey> keySelector, IComparer<TKey> comparer)
  1059. {
  1060. if (source == null) throw new ArgumentNullException("source");
  1061. if (keySelector == null) throw new ArgumentNullException("keySelector");
  1062. return new OrderedParallelQuery<TSource>(
  1063. new SortQueryOperator<TSource, TKey>(source, keySelector, comparer, false));
  1064. }
  1065. /// <summary>
  1066. /// Sorts in parallel the elements of a sequence in descending order according to a key.
  1067. /// </summary>
  1068. /// <remarks>
  1069. /// In contrast to the sequential implementation, this is not a stable sort.
  1070. /// See the remarks for OrderBy(ParallelQuery{TSource}, Func{TSource,TKey}) for
  1071. /// an approach to implementing a stable sort.
  1072. /// </remarks>
  1073. /// <typeparam name="TSource">The type of elements of <paramref name="source"/>.</typeparam>
  1074. /// <typeparam name="TKey">The type of the key returned by <paramref name="keySelector"/>.</typeparam>
  1075. /// <param name="source">A sequence of values to order.</param>
  1076. /// <param name="keySelector">A function to extract a key from an element.</param>
  1077. /// <returns>An OrderedParallelQuery{TSource} whose elements are sorted
  1078. /// descending according to a key.</returns>
  1079. /// <exception cref="T:System.ArgumentNullException">
  1080. /// <paramref name="source"/> or <paramref name="keySelector"/> is a null reference (Nothing in Visual Basic).
  1081. /// </exception>
  1082. public static OrderedParallelQuery<TSource> OrderByDescending<TSource, TKey>(
  1083. this ParallelQuery<TSource> source, Func<TSource, TKey> keySelector)
  1084. {
  1085. if (source == null) throw new ArgumentNullException("source");
  1086. if (keySelector == null) throw new ArgumentNullException("keySelector");
  1087. return new OrderedParallelQuery<TSource>(new SortQueryOperator<TSource, TKey>(source, keySelector, null, true));
  1088. }
  1089. /// <summary>
  1090. /// Sorts the elements of a sequence in descending order by using a specified comparer.
  1091. /// </summary>
  1092. /// <remarks>
  1093. /// In contrast to the sequential implementation, this is not a stable sort.
  1094. /// See the remarks for OrderBy(ParallelQuery{TSource}, Func{TSource,TKey}) for
  1095. /// an approach to implementing a stable sort.
  1096. /// </remarks>
  1097. /// <typeparam name="TSource">The type of elements of <paramref name="source"/>.</typeparam>
  1098. /// <typeparam name="TKey">The type of the key returned by <paramref name="keySelector"/>.</typeparam>
  1099. /// <param name="source">A sequence of values to order.</param>
  1100. /// <param name="keySelector">A function to extract a key from an element.</param>
  1101. /// <param name="comparer">An IComparer{TKey} to compare keys.</param>
  1102. /// <returns>An OrderedParallelQuery{TSource} whose elements are sorted descending
  1103. /// according to a key.</returns>
  1104. /// <exception cref="T:System.ArgumentNullException">
  1105. /// <paramref name="source"/> or <paramref name="keySelector"/> is a null reference (Nothing in Visual Basic).
  1106. /// </exception>
  1107. public static OrderedParallelQuery<TSource> OrderByDescending<TSource, TKey>(
  1108. this ParallelQuery<TSource> source, Func<TSource, TKey> keySelector, IComparer<TKey> comparer)
  1109. {
  1110. if (source == null) throw new ArgumentNullException("source");
  1111. if (keySelector == null) throw new ArgumentNullException("keySelector");
  1112. return new OrderedParallelQuery<TSource>(
  1113. new SortQueryOperator<TSource, TKey>(source, keySelector, comparer, true));
  1114. }
  1115. /// <summary>
  1116. /// Performs in parallel a subsequent ordering of the elements in a sequence
  1117. /// in ascending order according to a key.
  1118. /// </summary>
  1119. /// <remarks>
  1120. /// In contrast to the sequential implementation, this is not a stable sort.
  1121. /// See the remarks for OrderBy(ParallelQuery{TSource}, Func{TSource,TKey}) for
  1122. /// an approach to implementing a stable sort.
  1123. /// </remarks>
  1124. /// <typeparam name="TSource">The type of elements of <paramref name="source"/>.</typeparam>
  1125. /// <typeparam name="TKey">The type of the key returned by <paramref name="keySelector"/>.</typeparam>
  1126. /// <param name="source">An OrderedParallelQuery{TSource} than
  1127. /// contains elements to sort.</param>
  1128. /// <param name="keySelector">A function to extract a key from an element.</param>
  1129. /// <returns>An OrderedParallelQuery{TSource} whose elements are
  1130. /// sorted according to a key.</returns>
  1131. /// <exception cref="T:System.ArgumentNullException">
  1132. /// <paramref name="source"/> or <paramref name="keySelector"/> is a null reference (Nothing in Visual Basic).
  1133. /// </exception>
  1134. public static OrderedParallelQuery<TSource> ThenBy<TSource, TKey>(
  1135. this OrderedParallelQuery<TSource> source, Func<TSource, TKey> keySelector)
  1136. {
  1137. if (source == null) throw new ArgumentNullException("source");
  1138. if (keySelector == null) throw new ArgumentNullException("keySelector");
  1139. return new OrderedParallelQuery<TSource>(
  1140. (QueryOperator<TSource>)source.OrderedEnumerable.CreateOrderedEnumerable<TKey>(keySelector, null, false));
  1141. }
  1142. /// <summary>
  1143. /// Performs in parallel a subsequent ordering of the elements in a sequence in
  1144. /// ascending order by using a specified comparer.
  1145. /// </summary>
  1146. /// <remarks>
  1147. /// In contrast to the sequential implementation, this is not a stable sort.
  1148. /// See the remarks for OrderBy(ParallelQuery{TSource}, Func{TSource,TKey}) for
  1149. /// an approach to implementing a stable sort.
  1150. /// </remarks>
  1151. /// <typeparam name="TSource">The type of elements of <paramref name="source"/>.</typeparam>
  1152. /// <typeparam name="TKey">The type of the key returned by <paramref name="keySelector"/>.</typeparam>
  1153. /// <param name="source">An OrderedParallelQuery{TSource} that contains
  1154. /// elements to sort.</param>
  1155. /// <param name="keySelector">A function to extract a key from an element.</param>
  1156. /// <param name="comparer">An IComparer{TKey} to compare keys.</param>
  1157. /// <returns>An OrderedParallelQuery{TSource} whose elements are sorted
  1158. /// according to a key.</returns>
  1159. /// <exception cref="T:System.ArgumentNullException">
  1160. /// <paramref name="source"/> or <paramref name="keySelector"/> is a null reference (Nothing in Visual Basic).
  1161. /// </exception>
  1162. public static OrderedParallelQuery<TSource> ThenBy<TSource, TKey>(
  1163. this OrderedParallelQuery<TSource> source, Func<TSource, TKey> keySelector, IComparer<TKey> comparer)
  1164. {
  1165. if (source == null) throw new ArgumentNullException("source");
  1166. if (keySelector == null) throw new ArgumentNullException("keySelector");
  1167. return new OrderedParallelQuery<TSource>(
  1168. (QueryOperator<TSource>)source.OrderedEnumerable.CreateOrderedEnumerable<TKey>(keySelector, comparer, false));
  1169. }
  1170. /// <summary>
  1171. /// Performs in parallel a subsequent ordering of the elements in a sequence in
  1172. /// descending order, according to a key.
  1173. /// </summary>
  1174. /// <remarks>
  1175. /// In contrast to the sequential implementation, this is not a stable sort.
  1176. /// See the remarks for OrderBy(ParallelQuery{TSource}, Func{TSource,TKey}) for
  1177. /// an approach to implementing a stable sort.
  1178. /// </remarks>
  1179. /// <typeparam name="TSource">The type of elements of <paramref name="source"/>.</typeparam>
  1180. /// <typeparam name="TKey">The type of the key returned by <paramref name="keySelector"/>.</typeparam>
  1181. /// <param name="source">An OrderedParallelQuery{TSource} than contains
  1182. /// elements to sort.</param>
  1183. /// <param name="keySelector">A function to extract a key from an element.</param>
  1184. /// <returns>An OrderedParallelQuery{TSource} whose elements are sorted
  1185. /// descending according to a key.</returns>
  1186. /// <exception cref="T:System.ArgumentNullException">
  1187. /// <paramref name="source"/> or <paramref name="keySelector"/> is a null reference (Nothing in Visual Basic).
  1188. /// </exception>
  1189. public static OrderedParallelQuery<TSource> ThenByDescending<TSource, TKey>(
  1190. this OrderedParallelQuery<TSource> source, Func<TSource, TKey> keySelector)
  1191. {
  1192. if (source == null) throw new ArgumentNullException("source");
  1193. if (keySelector == null) throw new ArgumentNullException("keySelector");
  1194. return new OrderedParallelQuery<TSource>(
  1195. (QueryOperator<TSource>)source.OrderedEnumerable.CreateOrderedEnumerable<TKey>(keySelector, null, true));
  1196. }
  1197. /// <summary>
  1198. /// Performs in parallel a subsequent ordering of the elements in a sequence in descending
  1199. /// order by using a specified comparer.
  1200. /// </summary>
  1201. /// <remarks>
  1202. /// In contrast to the sequential implementation, this is not a stable sort.
  1203. /// See the remarks for OrderBy(ParallelQuery{TSource}, Func{TSource,TKey}) for
  1204. /// an approach to implementing a stable sort.
  1205. /// </remarks>
  1206. /// <typeparam name="TSource">The type of elements of <paramref name="source"/>.</typeparam>
  1207. /// <typeparam name="TKey">The type of the key returned by <paramref name="keySelector"/>.</typeparam>
  1208. /// <param name="source">An OrderedParallelQuery{TSource} than contains
  1209. /// elements to sort.</param>
  1210. /// <param name="keySelector">A function to extract a key from an element.</param>
  1211. /// <param name="comparer">An IComparer{TKey} to compare keys.</param>
  1212. /// <returns>An OrderedParallelQuery{TSource} whose elements are sorted
  1213. /// descending according to a key.</returns>
  1214. /// <exception cref="T:System.ArgumentNullException">
  1215. /// <paramref name="source"/> or <paramref name="keySelector"/> is a null reference (Nothing in Visual Basic).
  1216. /// </exception>
  1217. public static OrderedParallelQuery<TSource> ThenByDescending<TSource, TKey>(
  1218. this OrderedParallelQuery<TSource> source, Func<TSource, TKey> keySelector, IComparer<TKey> comparer)
  1219. {
  1220. if (source == null) throw new ArgumentNullException("source");
  1221. if (keySelector == null) throw new ArgumentNullException("keySelector");
  1222. return new OrderedParallelQuery<TSource>(
  1223. (QueryOperator<TSource>)source.OrderedEnumerable.CreateOrderedEnumerable<TKey>(keySelector, comparer, true));
  1224. }
  1225. //-----------------------------------------------------------------------------------
  1226. // A GroupBy operation groups inputs based on a key-selection routine, yielding a
  1227. // one-to-many value of key-to-elements to the consumer.
  1228. //
  1229. /// <summary>
  1230. /// Groups in parallel the elements of a sequence according to a specified key selector function.
  1231. /// </summary>
  1232. /// <typeparam name="TSource">The type of elements of <paramref name="source"/>.</typeparam>
  1233. /// <typeparam name="TKey">The type of the key returned by <paramref name="keySelector"/>.</typeparam>
  1234. /// <param name="source">An OrderedParallelQuery{TSource}than contains
  1235. /// elements to sort.</param>
  1236. /// <param name="keySelector">A function to extract a key from an element.</param>
  1237. /// <returns>An OrderedParallelQuery{TSource}whose elements are sorted
  1238. /// descending according to a key.</returns>
  1239. public static ParallelQuery<IGrouping<TKey, TSource>> GroupBy<TSource, TKey>(
  1240. this ParallelQuery<TSource> source, Func<TSource, TKey> keySelector)
  1241. {
  1242. return GroupBy<TSource, TKey>(source, keySelector, null);
  1243. }
  1244. /// <summary>
  1245. /// Groups in parallel the elements of a sequence according to a specified key selector function and compares the keys by using a specified comparer.
  1246. /// </summary>
  1247. /// <typeparam name="TSource">The type of elements of <paramref name="source"/>.</typeparam>
  1248. /// <typeparam name="TKey">The type of the key returned by <paramref name="keySelector"/>>.</typeparam>
  1249. /// <param name="source">An OrderedParallelQuery{TSource} than contains
  1250. /// elements to sort.</param>
  1251. /// <param name="keySelector">A function to extract a key from an element.</param>
  1252. /// <param name="comparer">An IComparer{TSource} to compare keys.</param>
  1253. /// <returns>An OrderedParallelQuery{TSource} whose elements are sorted
  1254. /// descending according to a key.</returns>
  1255. /// <exception cref="T:System.ArgumentNullException">
  1256. /// <paramref name="source"/> or <paramref name="keySelector"/> is a null reference (Nothing in Visual Basic).
  1257. /// </exception>
  1258. public static ParallelQuery<IGrouping<TKey, TSource>> GroupBy<TSource, TKey>(
  1259. this ParallelQuery<TSource> source, Func<TSource, TKey> keySelector, IEqualityComparer<TKey> comparer)
  1260. {
  1261. if (source == null) throw new ArgumentNullException("source");
  1262. if (keySelector == null) throw new ArgumentNullException("keySelector");
  1263. return new GroupByQueryOperator<TSource, TKey, TSource>(source, keySelector, null, comparer);
  1264. }
  1265. /// <summary>
  1266. /// Groups in parallel the elements of a sequence according to a specified key selector function and
  1267. /// projects the elements for each group by using a specified function.
  1268. /// </summary>
  1269. /// <typeparam name="TSource">The type of elements of <paramref name="source"/>.</typeparam>
  1270. /// <typeparam name="TKey">The type of the key returned by <paramref name="keySelector"/>.</typeparam>
  1271. /// <typeparam name="TElement">The type of the elements in the IGrouping</typeparam>
  1272. /// <param name="source">An OrderedParallelQuery&lt;(Of &lt;(TElement&gt;)&gt;) than contains
  1273. /// elements to sort.</param>
  1274. /// <param name="keySelector">A function to extract a key from an element.</param>
  1275. /// <param name="elementSelector">A function to map each source element to an element in an IGrouping.</param>
  1276. /// <returns>A ParallelQuery&lt;IGrouping&lt;TKey, TElement&gt;&gt; in C# or
  1277. /// ParallelQuery(Of IGrouping(Of TKey, TElement)) in Visual Basic where each IGrouping
  1278. /// generic object contains a collection of objects of type <typeparamref name="TElement"/> and a key.</returns>
  1279. /// <exception cref="T:System.ArgumentNullException">
  1280. /// <paramref name="source"/> or <paramref name="keySelector"/> or
  1281. /// <paramref name="elementSelector"/> is a null reference (Nothing in Visual Basic).
  1282. /// </exception>
  1283. public static ParallelQuery<IGrouping<TKey, TElement>> GroupBy<TSource, TKey, TElement>(
  1284. this ParallelQuery<TSource> source, Func<TSource, TKey> keySelector, Func<TSource, TElement> elementSelector)
  1285. {
  1286. return GroupBy<TSource, TKey, TElement>(source, keySelector, elementSelector, null);
  1287. }
  1288. /// <summary>
  1289. /// Groups in parallel the elements of a sequence according to a key selector function.
  1290. /// The keys are compared by using a comparer and each group's elements are projected by
  1291. /// using a specified function.
  1292. /// </summary>
  1293. /// <typeparam name="TSource">The type of elements of <paramref name="source"/>.</typeparam>
  1294. /// <typeparam name="TKey">The type of the key returned by <paramref name="keySelector"/>.</typeparam>
  1295. /// <typeparam name="TElement">The type of the elements in the IGrouping</typeparam>
  1296. /// <param name="source">An OrderedParallelQuery{TSource}than contains elements to sort.</param>
  1297. /// <param name="keySelector">A function to extract a key from an element.</param>
  1298. /// <param name="elementSelector">A function to map each source element to an element in an IGrouping.</param>
  1299. /// <param name="comparer">An IComparer{TSource} to compare keys.</param>
  1300. /// <returns>
  1301. /// A ParallelQuery{IGrouping{TKey, TElement}} in C# or
  1302. /// ParallelQuery(Of IGrouping(Of TKey, TElement)) in Visual Basic where each IGrouping
  1303. /// generic object contains a collection of objects of type <typeparamref name="TElement"/> and a key.
  1304. /// </returns>
  1305. /// <exception cref="T:System.ArgumentNullException">
  1306. /// <paramref name="source"/> or <paramref name="keySelector"/> or
  1307. /// <paramref name="elementSelector"/> is a null reference (Nothing in Visual Basic).
  1308. /// </exception>
  1309. public static ParallelQuery<IGrouping<TKey, TElement>> GroupBy<TSource, TKey, TElement>(
  1310. this ParallelQuery<TSource> source, Func<TSource, TKey> keySelector, Func<TSource, TElement> elementSelector, IEqualityComparer<TKey> comparer)
  1311. {
  1312. if (source == null) throw new ArgumentNullException("source");
  1313. if (keySelector == null) throw new ArgumentNullException("keySelector");
  1314. if (elementSelector == null) throw new ArgumentNullException("elementSelector");
  1315. return new GroupByQueryOperator<TSource, TKey, TElement>(source, keySelector, elementSelector, comparer);
  1316. }
  1317. //
  1318. // @PERF: We implement the GroupBy overloads that accept a resultSelector using a GroupBy followed by a Select. This
  1319. // adds some extra overhead, perhaps the most significant of which is an extra delegate invocation per element.
  1320. //
  1321. // One possible solution is to create two different versions of the GroupByOperator class, where one has a TResult
  1322. // generic type and the other does not. Since this results in code duplication, we will avoid doing that for now.
  1323. //
  1324. // Another possible solution is to only have the more general GroupByOperator. Unfortunately, implementing the less
  1325. // general overload (TResult == TElement) using the more general overload would likely result in unnecessary boxing
  1326. // and unboxing of each processed element in the cases where TResult is a value type, so that solution comes with
  1327. // a significant cost, too.
  1328. //
  1329. /// <summary>
  1330. /// Groups in parallel the elements of a sequence according to a specified
  1331. /// key selector function and creates a result value from each group and its key.
  1332. /// </summary>
  1333. /// <typeparam name="TSource">The type of the elements of <paramref name="source"/>.</typeparam>
  1334. /// <typeparam name="TKey">The type of the key returned by <paramref name="keySelector"/>.</typeparam>
  1335. /// <typeparam name="TResult">The type of the result value returned by <paramref name="resultSelector"/>.</typeparam>
  1336. /// <param name="source">A sequence whose elements to group.</param>
  1337. /// <param name="keySelector">A function to extract the key for each element.</param>
  1338. /// <param name="resultSelector">A function to create a result value from each group.</param>
  1339. /// <returns>A collection of elements of type <typeparamref name="TResult"/> where each element represents a
  1340. /// projection over a group and its key.</returns>
  1341. /// <exception cref="T:System.ArgumentNullException">
  1342. /// <paramref name="source"/> or <paramref name="keySelector"/> or
  1343. /// <paramref name="resultSelector"/> is a null reference (Nothing in Visual Basic).
  1344. /// </exception>
  1345. public static ParallelQuery<TResult> GroupBy<TSource, TKey, TResult>(
  1346. this ParallelQuery<TSource> source, Func<TSource, TKey> keySelector, Func<TKey, IEnumerable<TSource>, TResult> resultSelector)
  1347. {
  1348. if (resultSelector == null) throw new ArgumentNullException("resultSelector");
  1349. return source.GroupBy<TSource, TKey>(keySelector)
  1350. .Select<IGrouping<TKey, TSource>, TResult>(delegate(IGrouping<TKey, TSource> grouping) { return resultSelector(grouping.Key, grouping); });
  1351. }
  1352. /// <summary>
  1353. /// Groups in parallel the elements of a sequence according to a specified key selector function
  1354. /// and creates a result value from each group and its key. The keys are compared
  1355. /// by using a specified comparer.
  1356. /// </summary>
  1357. /// <typeparam name="TSource">The type of the elements of <paramref name="source"/>.</typeparam>
  1358. /// <typeparam name="TKey">The type of the key returned by <paramref name="keySelector"/>.</typeparam>
  1359. /// <typeparam name="TResult">The type of the result value returned by <paramref name="resultSelector"/>.</typeparam>
  1360. /// <param name="source">A sequence whose elements to group.</param>
  1361. /// <param name="keySelector">A function to extract the key for each element.</param>
  1362. /// <param name="resultSelector">A function to create a result value from each group.</param>
  1363. /// <param name="comparer">An IEqualityComparer{TKey} to compare keys.</param>
  1364. /// <returns>
  1365. /// An <B>ParallelQuery&lt;IGrouping&lt;TKey, TResult&gt;&gt;</B> in C# or
  1366. /// <B>ParallelQuery(Of IGrouping(Of TKey, TResult))</B> in Visual Basic where each
  1367. /// IGrouping&lt;(Of &lt;(TKey, TResult&gt;)&gt;) object contains a collection of objects
  1368. /// of type <typeparamref name="TResult"/> and a key.
  1369. /// </returns>
  1370. /// <exception cref="T:System.ArgumentNullException">
  1371. /// <paramref name="source"/> or <paramref name="keySelector"/> or
  1372. /// <paramref name="resultSelector"/> is a null reference (Nothing in Visual Basic).
  1373. /// </exception>
  1374. public static ParallelQuery<TResult> GroupBy<TSource, TKey, TResult>(
  1375. this ParallelQuery<TSource> source, Func<TSource, TKey> keySelector, Func<TKey, IEnumerable<TSource>, TResult> resultSelector, IEqualityComparer<TKey> comparer)
  1376. {
  1377. if (resultSelector == null) throw new ArgumentNullException("resultSelector");
  1378. return source.GroupBy<TSource, TKey>(keySelector, comparer).Select<IGrouping<TKey, TSource>, TResult>(
  1379. delegate(IGrouping<TKey, TSource> grouping) { return resultSelector(grouping.Key, grouping); });
  1380. }
  1381. /// <summary>
  1382. /// Groups in parallel the elements of a sequence according to a specified key
  1383. /// selector function and creates a result value from each group and its key.
  1384. /// The elements of each group are projected by using a specified function.
  1385. /// </summary>
  1386. /// <typeparam name="TSource">The type of the elements of <paramref name="source"/>.</typeparam>
  1387. /// <typeparam name="TKey">The type of the key returned by <paramref name="keySelector"/>.</typeparam>
  1388. /// <typeparam name="TElement">The type of the elements in each
  1389. /// IGrouping{TKey, TElement}.</typeparam>
  1390. /// <typeparam name="TResult">The type of the result value returned by <paramref name="resultSelector"/>.</typeparam>
  1391. /// <param name="source">A sequence whose elements to group.</param>
  1392. /// <param name="keySelector">A function to extract the key for each element.</param>
  1393. /// <param name="elementSelector">A function to map each source element to an element in an
  1394. /// IGrouping&lt;TKey, TElement&gt;.</param>
  1395. /// <param name="resultSelector">A function to create a result value from each group.</param>
  1396. /// <returns>A collection of elements of type <typeparamref name="TElement"/> where each element represents a
  1397. /// projection over a group and its key.</returns>
  1398. /// <exception cref="T:System.ArgumentNullException">
  1399. /// <paramref name="source"/> or <paramref name="keySelector"/> or
  1400. /// <paramref name="elementSelector"/> or <paramref name="resultSelector"/> is a null reference (Nothing in Visual Basic).
  1401. /// </exception>
  1402. public static ParallelQuery<TResult> GroupBy<TSource, TKey, TElement, TResult>(
  1403. this ParallelQuery<TSource> source, Func<TSource, TKey> keySelector, Func<TSource, TElement> elementSelector, Func<TKey, IEnumerable<TElement>, TResult> resultSelector)
  1404. {
  1405. if (resultSelector == null) throw new ArgumentNullException("resultSelector");
  1406. return source.GroupBy<TSource, TKey, TElement>(keySelector, elementSelector)
  1407. .Select<IGrouping<TKey, TElement>, TResult>(delegate(IGrouping<TKey, TElement> grouping) { return resultSelector(grouping.Key, grouping); });
  1408. }
  1409. /// <summary>
  1410. /// Groups the elements of a sequence according to a specified key selector function and
  1411. /// creates a result value from each group and its key. Key values are compared by using a
  1412. /// specified comparer, and the elements of each group are projected by using a specified function.
  1413. /// </summary>
  1414. /// <typeparam name="TSource">The type of the elements of <paramref name="source"/>.</typeparam>
  1415. /// <typeparam name="TKey">The type of the key returned by <paramref name="keySelector"/>.</typeparam>
  1416. /// <typeparam name="TElement">The type of the elements in each
  1417. /// IGrouping{TKey, TElement}.</typeparam>
  1418. /// <typeparam name="TResult">The type of the result value returned by <paramref name="resultSelector"/>.</typeparam>
  1419. /// <param name="source">A sequence whose elements to group.</param>
  1420. /// <param name="keySelector">A function to extract the key for each element.</param>
  1421. /// <param name="elementSelector">A function to map each source element to an element in an
  1422. /// IGrouping{Key, TElement}.</param>
  1423. /// <param name="resultSelector">A function to create a result value from each group.</param>
  1424. /// <param name="comparer">An IEqualityComparer{TKey} to compare keys.</param>
  1425. /// <returns>A collection of elements of type <typeparamref name="TResult"/> where each element represents a
  1426. /// projection over a group and its key.</returns>
  1427. /// <exception cref="T:System.ArgumentNullException">
  1428. /// <paramref name="source"/> or <paramref name="keySelector"/> or
  1429. /// <paramref name="elementSelector"/> or <paramref name="resultSelector"/> is a null reference (Nothing in Visual Basic).
  1430. /// </exception>
  1431. public static ParallelQuery<TResult> GroupBy<TSource, TKey, TElement, TResult>(
  1432. this ParallelQuery<TSource> source, Func<TSource, TKey> keySelector, Func<TSource, TElement> elementSelector, Func<TKey, IEnumerable<TElement>, TResult> resultSelector, IEqualityComparer<TKey> comparer)
  1433. {
  1434. if (resultSelector == null) throw new ArgumentNullException("resultSelector");
  1435. return source.GroupBy<TSource, TKey, TElement>(keySelector, elementSelector, comparer)
  1436. .Select<IGrouping<TKey, TElement>, TResult>(delegate(IGrouping<TKey, TElement> grouping) { return resultSelector(grouping.Key, grouping); });
  1437. }
  1438. /*===================================================================================
  1439. * AGGREGATION OPERATORS
  1440. *===================================================================================*/
  1441. //-----------------------------------------------------------------------------------
  1442. // Internal helper method that constructs an aggregation query operator and performs
  1443. // the actual execution/reduction before returning the result.
  1444. //
  1445. // Arguments:
  1446. // source - the data source over which aggregation is performed
  1447. // reduce - the binary reduction operator
  1448. // options - whether the operator is associative, commutative, both, or neither
  1449. //
  1450. // Return Value:
  1451. // The result of aggregation.
  1452. //
  1453. private static T PerformAggregation<T>(this ParallelQuery<T> source,
  1454. Func<T, T, T> reduce, T seed, bool seedIsSpecified, bool throwIfEmpty, QueryAggregationOptions options)
  1455. {
  1456. Contract.Assert(source != null);
  1457. Contract.Assert(reduce != null);
  1458. Contract.Assert(Enum.IsDefined(typeof(QueryAggregationOptions), options), "enum is out of range");
  1459. AssociativeAggregationOperator<T, T, T> op = new AssociativeAggregationOperator<T, T, T>(
  1460. source, seed, null, seedIsSpecified, reduce, reduce, delegate(T obj) { return obj; }, throwIfEmpty, options);
  1461. return op.Aggregate();
  1462. }
  1463. /// <summary>
  1464. /// Run an aggregation sequentially. If the user-provided reduction function throws an exception, wrap
  1465. /// it with an AggregateException.
  1466. /// </summary>
  1467. /// <param name="source"></param>
  1468. /// <param name="seed"></param>
  1469. /// <param name="seedIsSpecified">
  1470. /// if true, use the seed provided in the method argument
  1471. /// if false, use the first element of the sequence as the seed instead
  1472. /// </param>
  1473. /// <param name="func"></param>
  1474. private static TAccumulate PerformSequentialAggregation<TSource, TAccumulate>(
  1475. this ParallelQuery<TSource> source, TAccumulate seed, bool seedIsSpecified, Func<TAccumulate, TSource, TAccumulate> func)
  1476. {
  1477. Contract.Assert(source != null);
  1478. Contract.Assert(func != null);
  1479. Contract.Assert(seedIsSpecified || typeof(TSource) == typeof(TAccumulate));
  1480. using(IEnumerator<TSource> enumerator = source.GetEnumerator())
  1481. {
  1482. TAccumulate acc;
  1483. if (seedIsSpecified)
  1484. {
  1485. acc = seed;
  1486. }
  1487. else
  1488. {
  1489. // Take the first element as the seed
  1490. if (!enumerator.MoveNext())
  1491. {
  1492. throw new InvalidOperationException(SR.GetString(SR.NoElements));
  1493. }
  1494. acc = (TAccumulate)(object)enumerator.Current;
  1495. }
  1496. while (enumerator.MoveNext())
  1497. {
  1498. TSource elem = enumerator.Current;
  1499. // If the user delegate throws an exception, wrap it with an AggregateException
  1500. try
  1501. {
  1502. acc = func(acc, elem);
  1503. }
  1504. catch (ThreadAbortException)
  1505. {
  1506. // Do not wrap ThreadAbortExceptions
  1507. throw;
  1508. }
  1509. catch (Exception e)
  1510. {
  1511. throw new AggregateException(e);
  1512. }
  1513. }
  1514. return acc;
  1515. }
  1516. }
  1517. //-----------------------------------------------------------------------------------
  1518. // General purpose aggregation operators, allowing pluggable binary prefix operations.
  1519. //
  1520. /// <summary>
  1521. /// Applies in parallel an accumulator function over a sequence.
  1522. /// </summary>
  1523. /// <typeparam name="TSource">The type of the elements of <paramref name="source"/>.</typeparam>
  1524. /// <param name="source">A sequence to aggregate over.</param>
  1525. /// <param name="func">An accumulator function to be invoked on each element.</param>
  1526. /// <returns>The final accumulator value.</returns>
  1527. /// <exception cref="T:System.ArgumentNullException">
  1528. /// <paramref name="source"/> or <paramref name="func"/> is a null reference (Nothing in Visual Basic).
  1529. /// </exception>
  1530. /// <exception cref="T:System.InvalidOperationException">
  1531. /// <paramref name="source"/> contains no elements.
  1532. /// </exception>
  1533. /// <exception cref="T:System.AggregateException">
  1534. /// One or more exceptions occurred during the evaluation of the query.
  1535. /// </exception>
  1536. /// <exception cref="T:System.OperationCanceledException">
  1537. /// The query was canceled.
  1538. /// </exception>
  1539. public static TSource Aggregate<TSource>(
  1540. this ParallelQuery<TSource> source, Func<TSource, TSource, TSource> func)
  1541. {
  1542. return Aggregate<TSource>(source, func, QueryAggregationOptions.AssociativeCommutative);
  1543. }
  1544. internal static TSource Aggregate<TSource>(
  1545. this ParallelQuery<TSource> source, Func<TSource, TSource, TSource> func, QueryAggregationOptions options)
  1546. {
  1547. if (source == null) throw new ArgumentNullException("source");
  1548. if (func == null) throw new ArgumentNullException("func");
  1549. if ((~(QueryAggregationOptions.Associative | QueryAggregationOptions.Commutative) & options) != 0) throw new ArgumentOutOfRangeException("options");
  1550. if ((options & QueryAggregationOptions.Associative) != QueryAggregationOptions.Associative)
  1551. {
  1552. // Non associative aggregations must be run sequentially. We run the query in parallel
  1553. // and then perform the reduction over the resulting list.
  1554. return source.PerformSequentialAggregation(default(TSource), false, func);
  1555. }
  1556. else
  1557. {
  1558. // If associative, we can run this aggregation in parallel. The logic of the aggregation
  1559. // operator depends on whether the operator is commutative, so we also pass that information
  1560. // down to the query planning/execution engine.
  1561. return source.PerformAggregation<TSource>(func, default(TSource), false, true, options);
  1562. }
  1563. }
  1564. /// <summary>
  1565. /// Applies in parallel an accumulator function over a sequence.
  1566. /// The specified seed value is used as the initial accumulator value.
  1567. /// </summary>
  1568. /// <typeparam name="TSource">The type of the elements of <paramref name="source"/>.</typeparam>
  1569. /// <typeparam name="TAccumulate">The type of the accumulator value.</typeparam>
  1570. /// <param name="source">A sequence to aggregate over.</param>
  1571. /// <param name="seed">The initial accumulator value.</param>
  1572. /// <param name="func">An accumulator function to be invoked on each element.</param>
  1573. /// <returns>The final accumulator value.</returns>
  1574. /// <exception cref="T:System.ArgumentNullException">
  1575. /// <paramref name="source"/> or <paramref name="func"/> is a null reference (Nothing in Visual Basic).
  1576. /// </exception>
  1577. /// <exception cref="T:System.AggregateException">
  1578. /// One or more exceptions occurred during the evaluation of the query.
  1579. /// </exception>
  1580. /// <exception cref="T:System.OperationCanceledException">
  1581. /// The query was canceled.
  1582. /// </exception>
  1583. public static TAccumulate Aggregate<TSource, TAccumulate>(
  1584. this ParallelQuery<TSource> source, TAccumulate seed, Func<TAccumulate, TSource, TAccumulate> func)
  1585. {
  1586. return Aggregate<TSource, TAccumulate>(source, seed, func, QueryAggregationOptions.AssociativeCommutative);
  1587. }
  1588. internal static TAccumulate Aggregate<TSource, TAccumulate>(
  1589. this ParallelQuery<TSource> source, TAccumulate seed, Func<TAccumulate, TSource, TAccumulate> func, QueryAggregationOptions options)
  1590. {
  1591. if (source == null) throw new ArgumentNullException("source");
  1592. if (func == null) throw new ArgumentNullException("func");
  1593. if ((~(QueryAggregationOptions.Associative | QueryAggregationOptions.Commutative) & options) != 0) throw new ArgumentOutOfRangeException("options");
  1594. return source.PerformSequentialAggregation(seed, true, func);
  1595. }
  1596. /// <summary>
  1597. /// Applies in parallel an accumulator function over a sequence. The specified
  1598. /// seed value is used as the initial accumulator value, and the specified
  1599. /// function is used to select the result value.
  1600. /// </summary>
  1601. /// <typeparam name="TSource">The type of the elements of <paramref name="source"/>.</typeparam>
  1602. /// <typeparam name="TAccumulate">The type of the accumulator value.</typeparam>
  1603. /// <typeparam name="TResult">The type of the resulting value.</typeparam>
  1604. /// <param name="source">A sequence to aggregate over.</param>
  1605. /// <param name="seed">The initial accumulator value.</param>
  1606. /// <param name="func">An accumulator function to be invoked on each element.</param>
  1607. /// <param name="resultSelector">A function to transform the final accumulator value
  1608. /// into the result value.</param>
  1609. /// <returns>The transformed final accumulator value.</returns>
  1610. /// <exception cref="T:System.ArgumentNullException">
  1611. /// <paramref name="source"/> or <paramref name="func"/> or <paramref name="resultSelector"/> is a null reference (Nothing in Visual Basic).
  1612. /// </exception>
  1613. /// <exception cref="T:System.AggregateException">
  1614. /// One or more exceptions occurred during the evaluation of the query.
  1615. /// </exception>
  1616. /// <exception cref="T:System.OperationCanceledException">
  1617. /// The query was canceled.
  1618. /// </exception>
  1619. public static TResult Aggregate<TSource, TAccumulate, TResult>(
  1620. this ParallelQuery<TSource> source, TAccumulate seed, Func<TAccumulate, TSource, TAccumulate> func,
  1621. Func<TAccumulate, TResult> resultSelector)
  1622. {
  1623. if (source == null) throw new ArgumentNullException("source");
  1624. if (func == null) throw new ArgumentNullException("func");
  1625. if (resultSelector == null) throw new ArgumentNullException("resultSelector");
  1626. TAccumulate acc = source.PerformSequentialAggregation(seed, true, func);
  1627. try
  1628. {
  1629. return resultSelector(acc);
  1630. }
  1631. catch (ThreadAbortException)
  1632. {
  1633. // Do not wrap ThreadAbortExceptions
  1634. throw;
  1635. }
  1636. catch (Exception e)
  1637. {
  1638. throw new AggregateException(e);
  1639. }
  1640. }
  1641. /// <summary>
  1642. /// Applies in parallel an accumulator function over a sequence. This overload is not
  1643. /// available in the sequential implementation.
  1644. /// </summary>
  1645. /// <remarks>
  1646. /// This overload is specific to processing a parallelized query. A parallelized query may
  1647. /// partition the data source sequence into several sub-sequences (partitions).
  1648. /// The <paramref name="updateAccumulatorFunc"/> is invoked on each element within partitions.
  1649. /// Each partition then yields a single accumulated result. The <paramref name="combineAccumulatorsFunc"/>
  1650. /// is then invoked on the results of each partition to yield a single element. This element is then
  1651. /// transformed by the <paramref name="resultSelector"/> function.
  1652. /// </remarks>
  1653. /// <typeparam name="TSource">The type of the elements of <paramref name="source"/>.</typeparam>
  1654. /// <typeparam name="TAccumulate">The type of the accumulator value.</typeparam>
  1655. /// <typeparam name="TResult">The type of the resulting value.</typeparam>
  1656. /// <param name="source">A sequence to aggregate over.</param>
  1657. /// <param name="seed">The initial accumulator value.</param>
  1658. /// <param name="updateAccumulatorFunc">
  1659. /// An accumulator function to be invoked on each element in a partition.
  1660. /// </param>
  1661. /// <param name="combineAccumulatorsFunc">
  1662. /// An accumulator function to be invoked on the yielded element from each partition.
  1663. /// </param>
  1664. /// <param name="resultSelector">
  1665. /// A function to transform the final accumulator value into the result value.
  1666. /// </param>
  1667. /// <returns>The transformed final accumulator value.</returns>
  1668. /// <exception cref="T:System.ArgumentNullException">
  1669. /// <paramref name="source"/> or <paramref name="updateAccumulatorFunc"/>
  1670. /// or <paramref name="combineAccumulatorsFunc"/> or <paramref name="resultSelector"/> is a null reference (Nothing in Visual Basic).
  1671. /// </exception>
  1672. /// <exception cref="T:System.AggregateException">
  1673. /// One or more exceptions occurred during the evaluation of the query.
  1674. /// </exception>
  1675. /// <exception cref="T:System.OperationCanceledException">
  1676. /// The query was canceled.
  1677. /// </exception>
  1678. public static TResult Aggregate<TSource, TAccumulate, TResult>(
  1679. this ParallelQuery<TSource> source, TAccumulate seed, Func<TAccumulate, TSource, TAccumulate> updateAccumulatorFunc,
  1680. Func<TAccumulate, TAccumulate, TAccumulate> combineAccumulatorsFunc, Func<TAccumulate, TResult> resultSelector)
  1681. {
  1682. if (source == null) throw new ArgumentNullException("source");
  1683. if (updateAccumulatorFunc == null) throw new ArgumentNullException("updateAccumulatorFunc");
  1684. if (combineAccumulatorsFunc == null) throw new ArgumentNullException("combineAccumulatorsFunc");
  1685. if (resultSelector == null) throw new ArgumentNullException("resultSelector");
  1686. return new AssociativeAggregationOperator<TSource, TAccumulate, TResult>(
  1687. source, seed, null, true, updateAccumulatorFunc, combineAccumulatorsFunc, resultSelector,
  1688. false, QueryAggregationOptions.AssociativeCommutative).Aggregate();
  1689. }
  1690. /// <summary>
  1691. /// Applies in parallel an accumulator function over a sequence. This overload is not
  1692. /// available in the sequential implementation.
  1693. /// </summary>
  1694. /// <remarks>
  1695. /// This overload is specific to parallelized queries. A parallelized query may partition the data source sequence
  1696. /// into several sub-sequences (partitions). The <paramref name="updateAccumulatorFunc"/> is invoked
  1697. /// on each element within partitions. Each partition then yields a single accumulated result.
  1698. /// The <paramref name="combineAccumulatorsFunc"/>
  1699. /// is then invoked on the results of each partition to yield a single element. This element is then
  1700. /// transformed by the <paramref name="resultSelector"/> function.
  1701. /// </remarks>
  1702. /// <typeparam name="TSource">The type of the elements of <paramref name="source"/>.</typeparam>
  1703. /// <typeparam name="TAccumulate">The type of the accumulator value.</typeparam>
  1704. /// <typeparam name="TResult">The type of the resulting value.</typeparam>
  1705. /// <param name="source">A sequence to aggregate over.</param>
  1706. /// <param name="seedFactory">
  1707. /// A function that returns the initial accumulator value.
  1708. /// </param>
  1709. /// <param name="updateAccumulatorFunc">
  1710. /// An accumulator function to be invoked on each element in a partition.
  1711. /// </param>
  1712. /// <param name="combineAccumulatorsFunc">
  1713. /// An accumulator function to be invoked on the yielded element from each partition.
  1714. /// </param>
  1715. /// <param name="resultSelector">
  1716. /// A function to transform the final accumulator value into the result value.
  1717. /// </param>
  1718. /// <returns>The transformed final accumulator value.</returns>
  1719. /// <exception cref="T:System.ArgumentNullException">
  1720. /// <paramref name="source"/> or <paramref name="seedFactory"/> or <paramref name="updateAccumulatorFunc"/>
  1721. /// or <paramref name="combineAccumulatorsFunc"/> or <paramref name="resultSelector"/> is a null reference (Nothing in Visual Basic).
  1722. /// </exception>
  1723. /// <exception cref="T:System.AggregateException">
  1724. /// One or more exceptions occurred during the evaluation of the query.
  1725. /// </exception>
  1726. /// <exception cref="T:System.OperationCanceledException">
  1727. /// The query was canceled.
  1728. /// </exception>
  1729. public static TResult Aggregate<TSource, TAccumulate, TResult>(
  1730. this ParallelQuery<TSource> source,
  1731. Func<TAccumulate> seedFactory,
  1732. Func<TAccumulate, TSource, TAccumulate> updateAccumulatorFunc,
  1733. Func<TAccumulate, TAccumulate, TAccumulate> combineAccumulatorsFunc,
  1734. Func<TAccumulate, TResult> resultSelector)
  1735. {
  1736. if (source == null) throw new ArgumentNullException("source");
  1737. if (seedFactory == null) throw new ArgumentNullException("seedFactory");
  1738. if (updateAccumulatorFunc == null) throw new ArgumentNullException("updateAccumulatorFunc");
  1739. if (combineAccumulatorsFunc == null) throw new ArgumentNullException("combineAccumulatorsFunc");
  1740. if (resultSelector == null) throw new ArgumentNullException("resultSelector");
  1741. return new AssociativeAggregationOperator<TSource, TAccumulate, TResult>(
  1742. source, default(TAccumulate), seedFactory, true, updateAccumulatorFunc, combineAccumulatorsFunc, resultSelector,
  1743. false, QueryAggregationOptions.AssociativeCommutative).Aggregate();
  1744. }
  1745. //-----------------------------------------------------------------------------------
  1746. // Count and LongCount reductions.
  1747. //
  1748. /// <summary>
  1749. /// Returns the number of elements in a parallel sequence.
  1750. /// </summary>
  1751. /// <typeparam name="TSource">The type of the elements of <paramref name="source"/>.</typeparam>
  1752. /// <param name="source">A sequence that contains elements to be counted.</param>
  1753. /// <returns>The number of elements in the input sequence.</returns>
  1754. /// <exception cref="T:System.ArgumentNullException">
  1755. /// <paramref name="source"/> is a null reference (Nothing in Visual Basic).
  1756. /// </exception>
  1757. /// <exception cref="T:System.AggregateException">
  1758. /// The number of elements in source is larger than <see cref="M:System.Int32.MaxValue"/>.
  1759. /// -or-
  1760. /// One or more exceptions occurred during the evaluation of the query.
  1761. /// </exception>
  1762. /// <exception cref="T:System.OperationCanceledException">
  1763. /// The query was canceled.
  1764. /// </exception>
  1765. public static int Count<TSource>(this ParallelQuery<TSource> source)
  1766. {
  1767. if (source == null) throw new ArgumentNullException("source");
  1768. // If the data source is a collection, we can just return the count right away.
  1769. ParallelEnumerableWrapper<TSource> sourceAsWrapper = source as ParallelEnumerableWrapper<TSource>;
  1770. if (sourceAsWrapper != null)
  1771. {
  1772. ICollection<TSource> sourceAsCollection = sourceAsWrapper.WrappedEnumerable as ICollection<TSource>;
  1773. if (sourceAsCollection != null)
  1774. {
  1775. return sourceAsCollection.Count;
  1776. }
  1777. }
  1778. // Otherwise, enumerate the whole thing and aggregate a count.
  1779. checked
  1780. {
  1781. return new CountAggregationOperator<TSource>(source).Aggregate();
  1782. }
  1783. }
  1784. /// <summary>
  1785. /// Returns a number that represents how many elements in the specified
  1786. /// parallel sequence satisfy a condition.
  1787. /// </summary>
  1788. /// <typeparam name="TSource">The type of the elements of <paramref name="source"/>.</typeparam>
  1789. /// <param name="source">A sequence that contains elements to be counted.</param>
  1790. /// <param name="predicate">A function to test each element for a condition.</param>
  1791. /// <returns>
  1792. /// A number that represents how many elements in the sequence satisfy the condition
  1793. /// in the predicate function.
  1794. /// </returns>
  1795. /// <exception cref="T:System.ArgumentNullException">
  1796. /// <paramref name="source"/> or <paramref name="predicate"/> is a null reference (Nothing in Visual Basic).
  1797. /// </exception>
  1798. /// <exception cref="T:System.AggregateException">
  1799. /// The number of elements in source is larger than <see cref="M:System.Int32.MaxValue"/>.
  1800. /// -or-
  1801. /// One or more exceptions occurred during the evaluation of the query.
  1802. /// </exception>
  1803. /// <exception cref="T:System.OperationCanceledException">
  1804. /// The query was canceled.
  1805. /// </exception>
  1806. public static int Count<TSource>(this ParallelQuery<TSource> source, Func<TSource, bool> predicate)
  1807. {
  1808. if (source == null) throw new ArgumentNullException("source");
  1809. if (predicate == null) throw new ArgumentNullException("predicate");
  1810. // Construct a where operator to filter out unmatching elements, and then aggregate.
  1811. checked
  1812. {
  1813. return new CountAggregationOperator<TSource>(Where<TSource>(source, predicate)).Aggregate();
  1814. }
  1815. }
  1816. /// <summary>
  1817. /// Returns an Int64 that represents the total number of elements in a parallel sequence.
  1818. /// </summary>
  1819. /// <typeparam name="TSource">The type of the elements of <paramref name="source"/>.</typeparam>
  1820. /// <param name="source">A sequence that contains elements to be counted.</param>
  1821. /// <returns>The number of elements in the input sequence.</returns>
  1822. /// <exception cref="T:System.ArgumentNullException">
  1823. /// <paramref name="source"/> is a null reference (Nothing in Visual Basic).
  1824. /// </exception>
  1825. /// <exception cref="T:System.AggregateException">
  1826. /// The number of elements in source is larger than <see cref="M:System.Int64.MaxValue"/>.
  1827. /// -or-
  1828. /// One or more exceptions occurred during the evaluation of the query.
  1829. /// </exception>
  1830. /// <exception cref="T:System.OperationCanceledException">
  1831. /// The query was canceled.
  1832. /// </exception>
  1833. public static long LongCount<TSource>(this ParallelQuery<TSource> source)
  1834. {
  1835. if (source == null) throw new ArgumentNullException("source");
  1836. // If the data source is a collection, we can just return the count right away.
  1837. ParallelEnumerableWrapper<TSource> sourceAsWrapper = source as ParallelEnumerableWrapper<TSource>;
  1838. if (sourceAsWrapper != null)
  1839. {
  1840. ICollection<TSource> sourceAsCollection = sourceAsWrapper.WrappedEnumerable as ICollection<TSource>;
  1841. if (sourceAsCollection != null)
  1842. {
  1843. return sourceAsCollection.Count;
  1844. }
  1845. }
  1846. // Otherwise, enumerate the whole thing and aggregate a count.
  1847. return new LongCountAggregationOperator<TSource>(source).Aggregate();
  1848. }
  1849. /// <summary>
  1850. /// Returns an Int64 that represents how many elements in a parallel sequence satisfy a condition.
  1851. /// </summary>
  1852. /// <typeparam name="TSource">The type of the elements of <paramref name="source"/>.</typeparam>
  1853. /// <param name="source">A sequence that contains elements to be counted.</param>
  1854. /// <param name="predicate">A function to test each element for a condition.</param>
  1855. /// <returns>
  1856. /// A number that represents how many elements in the sequence satisfy the condition
  1857. /// in the predicate function.
  1858. /// </returns>
  1859. /// <exception cref="T:System.ArgumentNullException">
  1860. /// <paramref name="source"/> or <paramref name="predicate"/> is a null reference (Nothing in Visual Basic).
  1861. /// </exception>
  1862. /// <exception cref="T:System.AggregateException">
  1863. /// The number of elements in source is larger than <see cref="M:System.Int64.MaxValue"/>.
  1864. /// -or-
  1865. /// One or more exceptions occurred during the evaluation of the query.
  1866. /// </exception>
  1867. /// <exception cref="T:System.OperationCanceledException">
  1868. /// The query was canceled.
  1869. /// </exception>
  1870. public static long LongCount<TSource>(this ParallelQuery<TSource> source, Func<TSource, bool> predicate)
  1871. {
  1872. if (source == null) throw new ArgumentNullException("source");
  1873. if (predicate == null) throw new ArgumentNullException("predicate");
  1874. // Construct a where operator to filter out unmatching elements, and then aggregate.
  1875. return new LongCountAggregationOperator<TSource>(Where<TSource>(source, predicate)).Aggregate();
  1876. }
  1877. //-----------------------------------------------------------------------------------
  1878. // Sum aggregations.
  1879. //
  1880. /// <summary>
  1881. /// Computes in parallel the sum of a sequence of values.
  1882. /// </summary>
  1883. /// <param name="source">A sequence of values to calculate the sum of.</param>
  1884. /// <returns>The sum of the values in the sequence.</returns>
  1885. /// <exception cref="T:System.ArgumentNullException">
  1886. /// <paramref name="source"/> is a null reference (Nothing in Visual Basic).
  1887. /// </exception>
  1888. /// <exception cref="T:System.AggregateException">
  1889. /// The sum is larger than <see cref="M:System.Int32.MaxValue"/>.
  1890. /// -or-
  1891. /// One or more exceptions occurred during the evaluation of the query.
  1892. /// </exception>
  1893. /// <exception cref="T:System.OperationCanceledException">
  1894. /// The query was canceled.
  1895. /// </exception>
  1896. public static int Sum(this ParallelQuery<int> source)
  1897. {
  1898. if (source == null) throw new ArgumentNullException("source");
  1899. return new IntSumAggregationOperator(source).Aggregate();
  1900. }
  1901. /// <summary>
  1902. /// Computes in parallel the sum of a sequence of values.
  1903. /// </summary>
  1904. /// <param name="source">A sequence of values to calculate the sum of.</param>
  1905. /// <returns>The sum of the values in the sequence.</returns>
  1906. /// <exception cref="T:System.ArgumentNullException">
  1907. /// <paramref name="source"/> is a null reference (Nothing in Visual Basic).
  1908. /// </exception>
  1909. /// <exception cref="T:System.AggregateException">
  1910. /// The sum is larger than <see cref="M:System.Int32.MaxValue"/>.
  1911. /// -or-
  1912. /// One or more exceptions occurred during the evaluation of the query.
  1913. /// </exception>
  1914. /// <exception cref="T:System.OperationCanceledException">
  1915. /// The query was canceled.
  1916. /// </exception>
  1917. public static int? Sum(this ParallelQuery<int?> source)
  1918. {
  1919. if (source == null) throw new ArgumentNullException("source");
  1920. return new NullableIntSumAggregationOperator(source).Aggregate();
  1921. }
  1922. /// <summary>
  1923. /// Computes in parallel the sum of a sequence of values.
  1924. /// </summary>
  1925. /// <param name="source">A sequence of values to calculate the sum of.</param>
  1926. /// <returns>The sum of the values in the sequence.</returns>
  1927. /// <exception cref="T:System.ArgumentNullException">
  1928. /// <paramref name="source"/> is a null reference (Nothing in Visual Basic).
  1929. /// </exception>
  1930. /// <exception cref="T:System.AggregateException">
  1931. /// The sum is larger than <see cref="M:System.Int64.MaxValue"/>.
  1932. /// -or-
  1933. /// One or more exceptions occurred during the evaluation of the query.
  1934. /// </exception>
  1935. /// <exception cref="T:System.OperationCanceledException">
  1936. /// The query was canceled.
  1937. /// </exception>
  1938. public static long Sum(this ParallelQuery<long> source)
  1939. {
  1940. if (source == null) throw new ArgumentNullException("source");
  1941. return new LongSumAggregationOperator(source).Aggregate();
  1942. }
  1943. /// <summary>
  1944. /// Computes in parallel the sum of a sequence of values.
  1945. /// </summary>
  1946. /// <param name="source">A sequence of values to calculate the sum of.</param>
  1947. /// <returns>The sum of the values in the sequence.</returns>
  1948. /// <exception cref="T:System.ArgumentNullException">
  1949. /// <paramref name="source"/> is a null reference (Nothing in Visual Basic).
  1950. /// </exception>
  1951. /// <exception cref="T:System.AggregateException">
  1952. /// The sum is larger than <see cref="M:System.Int64.MaxValue"/>.
  1953. /// -or-
  1954. /// One or more exceptions occurred during the evaluation of the query.
  1955. /// </exception>
  1956. /// <exception cref="T:System.OperationCanceledException">
  1957. /// The query was canceled.
  1958. /// </exception>
  1959. public static long? Sum(this ParallelQuery<long?> source)
  1960. {
  1961. if (source == null) throw new ArgumentNullException("source");
  1962. return new NullableLongSumAggregationOperator(source).Aggregate();
  1963. }
  1964. /// <summary>
  1965. /// Computes in parallel the sum of a sequence of values.
  1966. /// </summary>
  1967. /// <param name="source">A sequence of values to calculate the sum of.</param>
  1968. /// <returns>The sum of the values in the sequence.</returns>
  1969. /// <exception cref="T:System.ArgumentNullException">
  1970. /// <paramref name="source"/> is a null reference (Nothing in Visual Basic).
  1971. /// </exception>
  1972. /// <exception cref="T:System.AggregateException">
  1973. /// One or more exceptions occurred during the evaluation of the query.
  1974. /// </exception>
  1975. /// <exception cref="T:System.OperationCanceledException">
  1976. /// The query was canceled.
  1977. /// </exception>
  1978. public static float Sum(this ParallelQuery<float> source)
  1979. {
  1980. if (source == null) throw new ArgumentNullException("source");
  1981. return new FloatSumAggregationOperator(source).Aggregate();
  1982. }
  1983. /// <summary>
  1984. /// Computes in parallel the sum of a sequence of values.
  1985. /// </summary>
  1986. /// <param name="source">A sequence of values to calculate the sum of.</param>
  1987. /// <returns>The sum of the values in the sequence.</returns>
  1988. /// <exception cref="T:System.ArgumentNullException">
  1989. /// <paramref name="source"/> is a null reference (Nothing in Visual Basic).
  1990. /// </exception>
  1991. /// <exception cref="T:System.AggregateException">
  1992. /// One or more exceptions occurred during the evaluation of the query.
  1993. /// </exception>
  1994. /// <exception cref="T:System.OperationCanceledException">
  1995. /// The query was canceled.
  1996. /// </exception>
  1997. public static float? Sum(this ParallelQuery<float?> source)
  1998. {
  1999. if (source == null) throw new ArgumentNullException("source");
  2000. return new NullableFloatSumAggregationOperator(source).Aggregate();
  2001. }
  2002. /// <summary>
  2003. /// Computes in parallel the sum of a sequence of values.
  2004. /// </summary>
  2005. /// <param name="source">A sequence of values to calculate the sum of.</param>
  2006. /// <returns>The sum of the values in the sequence.</returns>
  2007. /// <exception cref="T:System.ArgumentNullException">
  2008. /// <paramref name="source"/> is a null reference (Nothing in Visual Basic).
  2009. /// </exception>
  2010. /// <exception cref="T:System.AggregateException">
  2011. /// One or more exceptions occurred during the evaluation of the query.
  2012. /// </exception>
  2013. /// <exception cref="T:System.OperationCanceledException">
  2014. /// The query was canceled.
  2015. /// </exception>
  2016. public static double Sum(this ParallelQuery<double> source)
  2017. {
  2018. if (source == null) throw new ArgumentNullException("source");
  2019. return new DoubleSumAggregationOperator(source).Aggregate();
  2020. }
  2021. /// <summary>
  2022. /// Computes in parallel the sum of a sequence of values.
  2023. /// </summary>
  2024. /// <param name="source">A sequence of values to calculate the sum of.</param>
  2025. /// <returns>The sum of the values in the sequence.</returns>
  2026. /// <exception cref="T:System.ArgumentNullException">
  2027. /// <paramref name="source"/> is a null reference (Nothing in Visual Basic).
  2028. /// </exception>
  2029. /// <exception cref="T:System.AggregateException">
  2030. /// One or more exceptions occurred during the evaluation of the query.
  2031. /// </exception>
  2032. /// <exception cref="T:System.OperationCanceledException">
  2033. /// The query was canceled.
  2034. /// </exception>
  2035. public static double? Sum(this ParallelQuery<double?> source)
  2036. {
  2037. if (source == null) throw new ArgumentNullException("source");
  2038. return new NullableDoubleSumAggregationOperator(source).Aggregate();
  2039. }
  2040. /// <summary>
  2041. /// Computes in parallel the sum of a sequence of values.
  2042. /// </summary>
  2043. /// <param name="source">A sequence of values to calculate the sum of.</param>
  2044. /// <returns>The sum of the values in the sequence.</returns>
  2045. /// <exception cref="T:System.ArgumentNullException">
  2046. /// <paramref name="source"/> is a null reference (Nothing in Visual Basic).
  2047. /// </exception>
  2048. /// <exception cref="T:System.AggregateException">
  2049. /// The sum is larger than <see cref="M:System.Decimal.MaxValue"/>.
  2050. /// -or-
  2051. /// One or more exceptions occurred during the evaluation of the query.
  2052. /// </exception>
  2053. /// <exception cref="T:System.OperationCanceledException">
  2054. /// The query was canceled.
  2055. /// </exception>
  2056. public static decimal Sum(this ParallelQuery<decimal> source)
  2057. {
  2058. if (source == null) throw new ArgumentNullException("source");
  2059. return new DecimalSumAggregationOperator(source).Aggregate();
  2060. }
  2061. /// <summary>
  2062. /// Computes in parallel the sum of a sequence of values.
  2063. /// </summary>
  2064. /// <param name="source">A sequence of values to calculate the sum of.</param>
  2065. /// <returns>The sum of the values in the sequence.</returns>
  2066. /// <exception cref="T:System.ArgumentNullException">
  2067. /// <paramref name="source"/> is a null reference (Nothing in Visual Basic).
  2068. /// </exception>
  2069. /// <exception cref="T:System.AggregateException">
  2070. /// The sum is larger than <see cref="M:System.Decimal.MaxValue"/>.
  2071. /// -or-
  2072. /// One or more exceptions occurred during the evaluation of the query.
  2073. /// </exception>
  2074. /// <exception cref="T:System.OperationCanceledException">
  2075. /// The query was canceled.
  2076. /// </exception>
  2077. public static decimal? Sum(this ParallelQuery<decimal?> source)
  2078. {
  2079. if (source == null) throw new ArgumentNullException("source");
  2080. return new NullableDecimalSumAggregationOperator(source).Aggregate();
  2081. }
  2082. /// <summary>
  2083. /// Computes in parallel the sum of the sequence of values that are obtained
  2084. /// by invoking a transform function on each element of the input sequence.
  2085. /// </summary>
  2086. /// <param name="source">A sequence of values to calculate the sum of.</param>
  2087. /// <param name="selector">A transform function to apply to each element.</param>
  2088. /// <returns>The sum of the values in the sequence.</returns>
  2089. /// <exception cref="T:System.ArgumentNullException">
  2090. /// <paramref name="source"/> or <paramref name="selector"/> is a null reference (Nothing in Visual Basic).
  2091. /// </exception>
  2092. /// <exception cref="T:System.AggregateException">
  2093. /// The sum is larger than <see cref="M:System.Int32.MaxValue"/>.
  2094. /// -or-
  2095. /// One or more exceptions occurred during the evaluation of the query.
  2096. /// </exception>
  2097. /// <exception cref="T:System.OperationCanceledException">
  2098. /// The query was canceled.
  2099. /// </exception>
  2100. public static int Sum<TSource>(this ParallelQuery<TSource> source, Func<TSource, int> selector)
  2101. {
  2102. return source.Select(selector).Sum();
  2103. }
  2104. /// <summary>
  2105. /// Computes in parallel the sum of the sequence of values that are obtained
  2106. /// by invoking a transform function on each element of the input sequence.
  2107. /// </summary>
  2108. /// <typeparam name="TSource">The type of elements of <paramref name="source"/>.</typeparam>
  2109. /// <param name="source">A sequence of values to calculate the sum of.</param>
  2110. /// <param name="selector">A transform function to apply to each element.</param>
  2111. /// <returns>The sum of the values in the sequence.</returns>
  2112. /// <exception cref="T:System.ArgumentNullException">
  2113. /// <paramref name="source"/> or <paramref name="selector"/> is a null reference (Nothing in Visual Basic).
  2114. /// </exception>
  2115. /// <exception cref="T:System.AggregateException">
  2116. /// The sum is larger than <see cref="M:System.Int32.MaxValue"/>.
  2117. /// -or-
  2118. /// One or more exceptions occurred during the evaluation of the query.
  2119. /// </exception>
  2120. /// <exception cref="T:System.OperationCanceledException">
  2121. /// The query was canceled.
  2122. /// </exception>
  2123. public static int? Sum<TSource>(this ParallelQuery<TSource> source, Func<TSource, int?> selector)
  2124. {
  2125. return source.Select(selector).Sum();
  2126. }
  2127. /// <summary>
  2128. /// Computes in parallel the sum of the sequence of values that are obtained
  2129. /// by invoking a transform function on each element of the input sequence.
  2130. /// </summary>
  2131. /// <typeparam name="TSource">The type of elements of <paramref name="source"/>.</typeparam>
  2132. /// <param name="source">A sequence of values to calculate the sum of.</param>
  2133. /// <param name="selector">A transform function to apply to each element.</param>
  2134. /// <returns>The sum of the values in the sequence.</returns>
  2135. /// <exception cref="T:System.ArgumentNullException">
  2136. /// <paramref name="source"/> or <paramref name="selector"/> is a null reference (Nothing in Visual Basic).
  2137. /// </exception>
  2138. /// <exception cref="T:System.AggregateException">
  2139. /// The sum is larger than <see cref="M:System.Int64.MaxValue"/>.
  2140. /// -or-
  2141. /// One or more exceptions occurred during the evaluation of the query.
  2142. /// </exception>
  2143. /// <exception cref="T:System.OperationCanceledException">
  2144. /// The query was canceled.
  2145. /// </exception>
  2146. public static long Sum<TSource>(this ParallelQuery<TSource> source, Func<TSource, long> selector)
  2147. {
  2148. return source.Select(selector).Sum();
  2149. }
  2150. /// <summary>
  2151. /// Computes in parallel the sum of the sequence of values that are obtained
  2152. /// by invoking a transform function on each element of the input sequence.
  2153. /// </summary>
  2154. /// <typeparam name="TSource">The type of elements of <paramref name="source"/>.</typeparam>
  2155. /// <param name="source">A sequence of values to calculate the sum of.</param>
  2156. /// <param name="selector">A transform function to apply to each element.</param>
  2157. /// <returns>The sum of the values in the sequence.</returns>
  2158. /// <exception cref="T:System.ArgumentNullException">
  2159. /// <paramref name="source"/> or <paramref name="selector"/> is a null reference (Nothing in Visual Basic).
  2160. /// </exception>
  2161. /// <exception cref="T:System.AggregateException">
  2162. /// The sum is larger than <see cref="M:System.Int64.MaxValue"/>.
  2163. /// -or-
  2164. /// One or more exceptions occurred during the evaluation of the query.
  2165. /// </exception>
  2166. /// <exception cref="T:System.OperationCanceledException">
  2167. /// The query was canceled.
  2168. /// </exception>
  2169. public static long? Sum<TSource>(this ParallelQuery<TSource> source, Func<TSource, long?> selector)
  2170. {
  2171. return source.Select(selector).Sum();
  2172. }
  2173. /// <summary>
  2174. /// Computes in parallel the sum of the sequence of values that are obtained
  2175. /// by invoking a transform function on each element of the input sequence.
  2176. /// </summary>
  2177. /// <typeparam name="TSource">The type of elements of <paramref name="source"/>.</typeparam>
  2178. /// <param name="source">A sequence of values to calculate the sum of.</param>
  2179. /// <param name="selector">A transform function to apply to each element.</param>
  2180. /// <returns>The sum of the values in the sequence.</returns>
  2181. /// <exception cref="T:System.ArgumentNullException">
  2182. /// <paramref name="source"/> or <paramref name="selector"/> is a null reference (Nothing in Visual Basic).
  2183. /// </exception>
  2184. /// <exception cref="T:System.AggregateException">
  2185. /// One or more exceptions occurred during the evaluation of the query.
  2186. /// </exception>
  2187. /// <exception cref="T:System.OperationCanceledException">
  2188. /// The query was canceled.
  2189. /// </exception>
  2190. public static float Sum<TSource>(this ParallelQuery<TSource> source, Func<TSource, float> selector)
  2191. {
  2192. return source.Select(selector).Sum();
  2193. }
  2194. /// <summary>
  2195. /// Computes in parallel the sum of the sequence of values that are obtained
  2196. /// by invoking a transform function on each element of the input sequence.
  2197. /// </summary>
  2198. /// <typeparam name="TSource">The type of elements of <paramref name="source"/>.</typeparam>
  2199. /// <param name="source">A sequence of values to calculate the sum of.</param>
  2200. /// <param name="selector">A transform function to apply to each element.</param>
  2201. /// <returns>The sum of the values in the sequence.</returns>
  2202. /// <exception cref="T:System.ArgumentNullException">
  2203. /// <paramref name="source"/> or <paramref name="selector"/> is a null reference (Nothing in Visual Basic).
  2204. /// </exception>
  2205. /// <exception cref="T:System.AggregateException">
  2206. /// One or more exceptions occurred during the evaluation of the query.
  2207. /// </exception>
  2208. /// <exception cref="T:System.OperationCanceledException">
  2209. /// The query was canceled.
  2210. /// </exception>
  2211. public static float? Sum<TSource>(this ParallelQuery<TSource> source, Func<TSource, float?> selector)
  2212. {
  2213. return source.Select(selector).Sum();
  2214. }
  2215. /// <summary>
  2216. /// Computes in parallel the sum of the sequence of values that are obtained
  2217. /// by invoking a transform function on each element of the input sequence.
  2218. /// </summary>
  2219. /// <typeparam name="TSource">The type of elements of <paramref name="source"/>.</typeparam>
  2220. /// <param name="source">A sequence of values to calculate the sum of.</param>
  2221. /// <param name="selector">A transform function to apply to each element.</param>
  2222. /// <returns>The sum of the values in the sequence.</returns>
  2223. /// <exception cref="T:System.ArgumentNullException">
  2224. /// <paramref name="source"/> or <paramref name="selector"/> is a null reference (Nothing in Visual Basic).
  2225. /// </exception>
  2226. /// <exception cref="T:System.AggregateException">
  2227. /// One or more exceptions occurred during the evaluation of the query.
  2228. /// </exception>
  2229. /// <exception cref="T:System.OperationCanceledException">
  2230. /// The query was canceled.
  2231. /// </exception>
  2232. public static double Sum<TSource>(this ParallelQuery<TSource> source, Func<TSource, double> selector)
  2233. {
  2234. return source.Select(selector).Sum();
  2235. }
  2236. /// <summary>
  2237. /// Computes in parallel the sum of the sequence of values that are obtained
  2238. /// by invoking a transform function on each element of the input sequence.
  2239. /// </summary>
  2240. /// <typeparam name="TSource">The type of elements of <paramref name="source"/>.</typeparam>
  2241. /// <param name="source">A sequence of values to calculate the sum of.</param>
  2242. /// <param name="selector">A transform function to apply to each element.</param>
  2243. /// <returns>The sum of the values in the sequence.</returns>
  2244. /// <exception cref="T:System.ArgumentNullException">
  2245. /// <paramref name="source"/> or <paramref name="selector"/> is a null reference (Nothing in Visual Basic).
  2246. /// </exception>
  2247. /// <exception cref="T:System.AggregateException">
  2248. /// One or more exceptions occurred during the evaluation of the query.
  2249. /// </exception>
  2250. /// <exception cref="T:System.OperationCanceledException">
  2251. /// The query was canceled.
  2252. /// </exception>
  2253. public static double? Sum<TSource>(this ParallelQuery<TSource> source, Func<TSource, double?> selector)
  2254. {
  2255. return source.Select(selector).Sum();
  2256. }
  2257. /// <summary>
  2258. /// Computes in parallel the sum of the sequence of values that are obtained
  2259. /// by invoking a transform function on each element of the input sequence.
  2260. /// </summary>
  2261. /// <typeparam name="TSource">The type of elements of <paramref name="source"/>.</typeparam>
  2262. /// <param name="source">A sequence of values to calculate the sum of.</param>
  2263. /// <param name="selector">A transform function to apply to each element.</param>
  2264. /// <returns>The sum of the values in the sequence.</returns>
  2265. /// <exception cref="T:System.ArgumentNullException">
  2266. /// <paramref name="source"/> or <paramref name="selector"/> is a null reference (Nothing in Visual Basic).
  2267. /// </exception>
  2268. /// <exception cref="T:System.AggregateException">
  2269. /// The sum is larger than <see cref="M:System.Decimal.MaxValue"/>.
  2270. /// -or-
  2271. /// One or more exceptions occurred during the evaluation of the query.
  2272. /// </exception>
  2273. /// <exception cref="T:System.OperationCanceledException">
  2274. /// The query was canceled.
  2275. /// </exception>
  2276. public static decimal Sum<TSource>(this ParallelQuery<TSource> source, Func<TSource, decimal> selector)
  2277. {
  2278. return source.Select(selector).Sum();
  2279. }
  2280. /// <summary>
  2281. /// Computes in parallel the sum of the sequence of values that are obtained
  2282. /// by invoking a transform function on each element of the input sequence.
  2283. /// </summary>
  2284. /// <typeparam name="TSource">The type of elements of <paramref name="source"/>.</typeparam>
  2285. /// <param name="source">A sequence of values to calculate the sum of.</param>
  2286. /// <param name="selector">A transform function to apply to each element.</param>
  2287. /// <returns>The sum of the values in the sequence.</returns>
  2288. /// <exception cref="T:System.ArgumentNullException">
  2289. /// <paramref name="source"/> or <paramref name="selector"/> is a null reference (Nothing in Visual Basic).
  2290. /// </exception>
  2291. /// <exception cref="T:System.AggregateException">
  2292. /// The sum is larger than <see cref="M:System.Decimal.MaxValue"/>.
  2293. /// -or-
  2294. /// One or more exceptions occurred during the evaluation of the query.
  2295. /// </exception>
  2296. /// <exception cref="T:System.OperationCanceledException">
  2297. /// The query was canceled.
  2298. /// </exception>
  2299. public static decimal? Sum<TSource>(this ParallelQuery<TSource> source, Func<TSource, decimal?> selector)
  2300. {
  2301. return source.Select(selector).Sum();
  2302. }
  2303. //-----------------------------------------------------------------------------------
  2304. // Helper methods used for Min/Max aggregations below. This class can create a whole
  2305. // bunch of type-specific delegates that are passed to the general aggregation
  2306. // infrastructure. All comparisons are performed using the Comparer<T>.Default
  2307. // comparator. LINQ doesn't offer a way to override this, so neither do we.
  2308. //
  2309. // @PERF: we'll eventually want inlined primitive providers that use IL instructions
  2310. // for comparison instead of the Comparer<T>.CompareTo method.
  2311. //
  2312. //-----------------------------------------------------------------------------------
  2313. // Min aggregations.
  2314. //
  2315. /// <summary>
  2316. /// Returns the minimum value in a parallel sequence of values.
  2317. /// </summary>
  2318. /// <param name="source">A sequence of values to determine the minimum value of.</param>
  2319. /// <returns>The minimum value in the sequence.</returns>
  2320. /// <exception cref="T:System.ArgumentNullException">
  2321. /// <paramref name="source"/> is a null reference (Nothing in Visual Basic).
  2322. /// </exception>
  2323. /// <exception cref="T:System.InvalidOperationException">
  2324. /// <paramref name="source"/> contains no elements.
  2325. /// </exception>
  2326. /// <exception cref="T:System.AggregateException">
  2327. /// One or more exceptions occurred during the evaluation of the query.
  2328. /// </exception>
  2329. /// <exception cref="T:System.OperationCanceledException">
  2330. /// The query was canceled.
  2331. /// </exception>
  2332. public static int Min(this ParallelQuery<int> source)
  2333. {
  2334. if (source == null) throw new ArgumentNullException("source");
  2335. return new IntMinMaxAggregationOperator(source, -1).Aggregate();
  2336. }
  2337. /// <summary>
  2338. /// Returns the minimum value in a parallel sequence of values.
  2339. /// </summary>
  2340. /// <param name="source">A sequence of values to determine the minimum value of.</param>
  2341. /// <returns>The minimum value in the sequence.</returns>
  2342. /// <exception cref="T:System.ArgumentNullException">
  2343. /// <paramref name="source"/> is a null reference (Nothing in Visual Basic).
  2344. /// </exception>
  2345. /// <exception cref="T:System.AggregateException">
  2346. /// One or more exceptions occurred during the evaluation of the query.
  2347. /// </exception>
  2348. /// <exception cref="T:System.OperationCanceledException">
  2349. /// The query was canceled.
  2350. /// </exception>
  2351. public static int? Min(this ParallelQuery<int?> source)
  2352. {
  2353. if (source == null) throw new ArgumentNullException("source");
  2354. return new NullableIntMinMaxAggregationOperator(source, -1).Aggregate();
  2355. }
  2356. /// <summary>
  2357. /// Returns the minimum value in a parallel sequence of values.
  2358. /// </summary>
  2359. /// <param name="source">A sequence of values to determine the minimum value of.</param>
  2360. /// <returns>The minimum value in the sequence.</returns>
  2361. /// <exception cref="T:System.ArgumentNullException">
  2362. /// <paramref name="source"/> is a null reference (Nothing in Visual Basic).
  2363. /// </exception>
  2364. /// <exception cref="T:System.InvalidOperationException">
  2365. /// <paramref name="source"/> contains no elements.
  2366. /// </exception>
  2367. /// <exception cref="T:System.AggregateException">
  2368. /// One or more exceptions occurred during the evaluation of the query.
  2369. /// </exception>
  2370. /// <exception cref="T:System.OperationCanceledException">
  2371. /// The query was canceled.
  2372. /// </exception>
  2373. public static long Min(this ParallelQuery<long> source)
  2374. {
  2375. if (source == null) throw new ArgumentNullException("source");
  2376. return new LongMinMaxAggregationOperator(source, -1).Aggregate();
  2377. }
  2378. /// <summary>
  2379. /// Returns the minimum value in a parallel sequence of values.
  2380. /// </summary>
  2381. /// <param name="source">A sequence of values to determine the minimum value of.</param>
  2382. /// <returns>The minimum value in the sequence.</returns>
  2383. /// <exception cref="T:System.ArgumentNullException">
  2384. /// <paramref name="source"/> is a null reference (Nothing in Visual Basic).
  2385. /// </exception>
  2386. /// <exception cref="T:System.AggregateException">
  2387. /// One or more exceptions occurred during the evaluation of the query.
  2388. /// </exception>
  2389. /// <exception cref="T:System.OperationCanceledException">
  2390. /// The query was canceled.
  2391. /// </exception>
  2392. public static long? Min(this ParallelQuery<long?> source)
  2393. {
  2394. if (source == null) throw new ArgumentNullException("source");
  2395. return new NullableLongMinMaxAggregationOperator(source, -1).Aggregate();
  2396. }
  2397. /// <summary>
  2398. /// Returns the minimum value in a parallel sequence of values.
  2399. /// </summary>
  2400. /// <param name="source">A sequence of values to determine the minimum value of.</param>
  2401. /// <returns>The minimum value in the sequence.</returns>
  2402. /// <exception cref="T:System.ArgumentNullException">
  2403. /// <paramref name="source"/> is a null reference (Nothing in Visual Basic).
  2404. /// </exception>
  2405. /// <exception cref="T:System.InvalidOperationException">
  2406. /// <paramref name="source"/> contains no elements.
  2407. /// </exception>
  2408. /// <exception cref="T:System.AggregateException">
  2409. /// One or more exceptions occurred during the evaluation of the query.
  2410. /// </exception>
  2411. /// <exception cref="T:System.OperationCanceledException">
  2412. /// The query was canceled.
  2413. /// </exception>
  2414. public static float Min(this ParallelQuery<float> source)
  2415. {
  2416. if (source == null) throw new ArgumentNullException("source");
  2417. return new FloatMinMaxAggregationOperator(source, -1).Aggregate();
  2418. }
  2419. /// <summary>
  2420. /// Returns the minimum value in a parallel sequence of values.
  2421. /// </summary>
  2422. /// <param name="source">A sequence of values to determine the minimum value of.</param>
  2423. /// <returns>The minimum value in the sequence.</returns>
  2424. /// <exception cref="T:System.ArgumentNullException">
  2425. /// <paramref name="source"/> is a null reference (Nothing in Visual Basic).
  2426. /// </exception>
  2427. /// <exception cref="T:System.AggregateException">
  2428. /// One or more exceptions occurred during the evaluation of the query.
  2429. /// </exception>
  2430. /// <exception cref="T:System.OperationCanceledException">
  2431. /// The query was canceled.
  2432. /// </exception>
  2433. public static float? Min(this ParallelQuery<float?> source)
  2434. {
  2435. if (source == null) throw new ArgumentNullException("source");
  2436. return new NullableFloatMinMaxAggregationOperator(source, -1).Aggregate();
  2437. }
  2438. /// <summary>
  2439. /// Returns the minimum value in a parallel sequence of values.
  2440. /// </summary>
  2441. /// <param name="source">A sequence of values to determine the minimum value of.</param>
  2442. /// <returns>The minimum value in the sequence.</returns>
  2443. /// <exception cref="T:System.ArgumentNullException">
  2444. /// <paramref name="source"/> is a null reference (Nothing in Visual Basic).
  2445. /// </exception>
  2446. /// <exception cref="T:System.InvalidOperationException">
  2447. /// <paramref name="source"/> contains no elements.
  2448. /// </exception>
  2449. /// <exception cref="T:System.AggregateException">
  2450. /// One or more exceptions occurred during the evaluation of the query.
  2451. /// </exception>
  2452. /// <exception cref="T:System.OperationCanceledException">
  2453. /// The query was canceled.
  2454. /// </exception>
  2455. public static double Min(this ParallelQuery<double> source)
  2456. {
  2457. if (source == null) throw new ArgumentNullException("source");
  2458. return new DoubleMinMaxAggregationOperator(source, -1).Aggregate();
  2459. }
  2460. /// <summary>
  2461. /// Returns the minimum value in a parallel sequence of values.
  2462. /// </summary>
  2463. /// <param name="source">A sequence of values to determine the minimum value of.</param>
  2464. /// <returns>The minimum value in the sequence.</returns>
  2465. /// <exception cref="T:System.ArgumentNullException">
  2466. /// <paramref name="source"/> is a null reference (Nothing in Visual Basic).
  2467. /// </exception>
  2468. /// <exception cref="T:System.AggregateException">
  2469. /// One or more exceptions occurred during the evaluation of the query.
  2470. /// </exception>
  2471. /// <exception cref="T:System.OperationCanceledException">
  2472. /// The query was canceled.
  2473. /// </exception>
  2474. public static double? Min(this ParallelQuery<double?> source)
  2475. {
  2476. if (source == null) throw new ArgumentNullException("source");
  2477. return new NullableDoubleMinMaxAggregationOperator(source, -1).Aggregate();
  2478. }
  2479. /// <summary>
  2480. /// Returns the minimum value in a parallel sequence of values.
  2481. /// </summary>
  2482. /// <param name="source">A sequence of values to determine the minimum value of.</param>
  2483. /// <returns>The minimum value in the sequence.</returns>
  2484. /// <exception cref="T:System.ArgumentNullException">
  2485. /// <paramref name="source"/> is a null reference (Nothing in Visual Basic).
  2486. /// </exception>
  2487. /// <exception cref="T:System.InvalidOperationException">
  2488. /// <paramref name="source"/> contains no elements.
  2489. /// </exception>
  2490. /// <exception cref="T:System.AggregateException">
  2491. /// One or more exceptions occurred during the evaluation of the query.
  2492. /// </exception>
  2493. /// <exception cref="T:System.OperationCanceledException">
  2494. /// The query was canceled.
  2495. /// </exception>
  2496. public static decimal Min(this ParallelQuery<decimal> source)
  2497. {
  2498. if (source == null) throw new ArgumentNullException("source");
  2499. return new DecimalMinMaxAggregationOperator(source, -1).Aggregate();
  2500. }
  2501. /// <summary>
  2502. /// Returns the minimum value in a parallel sequence of values.
  2503. /// </summary>
  2504. /// <param name="source">A sequence of values to determine the minimum value of.</param>
  2505. /// <returns>The minimum value in the sequence.</returns>
  2506. /// <exception cref="T:System.ArgumentNullException">
  2507. /// <paramref name="source"/> is a null reference (Nothing in Visual Basic).
  2508. /// </exception>
  2509. /// <exception cref="T:System.AggregateException">
  2510. /// One or more exceptions occurred during the evaluation of the query.
  2511. /// </exception>
  2512. /// <exception cref="T:System.OperationCanceledException">
  2513. /// The query was canceled.
  2514. /// </exception>
  2515. public static decimal? Min(this ParallelQuery<decimal?> source)
  2516. {
  2517. if (source == null) throw new ArgumentNullException("source");
  2518. return new NullableDecimalMinMaxAggregationOperator(source, -1).Aggregate();
  2519. }
  2520. /// <summary>
  2521. /// Returns the minimum value in a parallel sequence of values.
  2522. /// </summary>
  2523. /// <typeparam name="TSource">The type of elements of <paramref name="source"/>.</typeparam>
  2524. /// <param name="source">A sequence of values to determine the minimum value of.</param>
  2525. /// <returns>The minimum value in the sequence.</returns>
  2526. /// <exception cref="T:System.ArgumentNullException">
  2527. /// <paramref name="source"/> is a null reference (Nothing in Visual Basic).
  2528. /// </exception>
  2529. /// <exception cref="T:System.InvalidOperationException">
  2530. /// <paramref name="source"/> contains no elements and <typeparamref name="TSource"/> is a non-nullable value type.
  2531. /// </exception>
  2532. /// <exception cref="T:System.AggregateException">
  2533. /// One or more exceptions occurred during the evaluation of the query.
  2534. /// </exception>
  2535. /// <exception cref="T:System.OperationCanceledException">
  2536. /// The query was canceled.
  2537. /// </exception>
  2538. public static TSource Min<TSource>(this ParallelQuery<TSource> source)
  2539. {
  2540. if (source == null) throw new ArgumentNullException("source");
  2541. return AggregationMinMaxHelpers<TSource>.ReduceMin(source);
  2542. }
  2543. /// <summary>
  2544. /// Invokes in parallel a transform function on each element of a
  2545. /// sequence and returns the minimum value.
  2546. /// </summary>
  2547. /// <typeparam name="TSource">The type of elements of <paramref name="source"/>.</typeparam>
  2548. /// <param name="source">A sequence of values to determine the minimum value of.</param>
  2549. /// <param name="selector">A transform function to apply to each element.</param>
  2550. /// <returns>The minimum value in the sequence.</returns>
  2551. /// <exception cref="T:System.ArgumentNullException">
  2552. /// <paramref name="source"/> or <paramref name="selector"/> is a null reference (Nothing in Visual Basic).
  2553. /// </exception>
  2554. /// <exception cref="T:System.InvalidOperationException">
  2555. /// <paramref name="source"/> contains no elements.
  2556. /// </exception>
  2557. /// <exception cref="T:System.AggregateException">
  2558. /// One or more exceptions occurred during the evaluation of the query.
  2559. /// </exception>
  2560. /// <exception cref="T:System.OperationCanceledException">
  2561. /// The query was canceled.
  2562. /// </exception>
  2563. public static int Min<TSource>(this ParallelQuery<TSource> source, Func<TSource, int> selector)
  2564. {
  2565. return source.Select<TSource, int>(selector).Min<int>();
  2566. }
  2567. /// <summary>
  2568. /// Invokes in parallel a transform function on each element of a
  2569. /// sequence and returns the minimum value.
  2570. /// </summary>
  2571. /// <typeparam name="TSource">The type of elements of <paramref name="source"/>.</typeparam>
  2572. /// <param name="source">A sequence of values to determine the minimum value of.</param>
  2573. /// <param name="selector">A transform function to apply to each element.</param>
  2574. /// <returns>The minimum value in the sequence.</returns>
  2575. /// <exception cref="T:System.ArgumentNullException">
  2576. /// <paramref name="source"/> or <paramref name="selector"/> is a null reference (Nothing in Visual Basic).
  2577. /// </exception>
  2578. /// <exception cref="T:System.AggregateException">
  2579. /// One or more exceptions occurred during the evaluation of the query.
  2580. /// </exception>
  2581. /// <exception cref="T:System.OperationCanceledException">
  2582. /// The query was canceled.
  2583. /// </exception>
  2584. public static int? Min<TSource>(this ParallelQuery<TSource> source, Func<TSource, int?> selector)
  2585. {
  2586. return source.Select<TSource, int?>(selector).Min<int?>();
  2587. }
  2588. /// <summary>
  2589. /// Invokes in parallel a transform function on each element of a
  2590. /// sequence and returns the minimum value.
  2591. /// </summary>
  2592. /// <typeparam name="TSource">The type of elements of <paramref name="source"/>.</typeparam>
  2593. /// <param name="source">A sequence of values to determine the minimum value of.</param>
  2594. /// <param name="selector">A transform function to apply to each element.</param>
  2595. /// <returns>The minimum value in the sequence.</returns>
  2596. /// <exception cref="T:System.ArgumentNullException">
  2597. /// <paramref name="source"/> or <paramref name="selector"/> is a null reference (Nothing in Visual Basic).
  2598. /// </exception>
  2599. /// <exception cref="T:System.InvalidOperationException">
  2600. /// <paramref name="source"/> contains no elements.
  2601. /// </exception>
  2602. /// <exception cref="T:System.AggregateException">
  2603. /// One or more exceptions occurred during the evaluation of the query.
  2604. /// </exception>
  2605. /// <exception cref="T:System.OperationCanceledException">
  2606. /// The query was canceled.
  2607. /// </exception>
  2608. public static long Min<TSource>(this ParallelQuery<TSource> source, Func<TSource, long> selector)
  2609. {
  2610. return source.Select<TSource, long>(selector).Min<long>();
  2611. }
  2612. /// <summary>
  2613. /// Invokes in parallel a transform function on each element of a
  2614. /// sequence and returns the minimum value.
  2615. /// </summary>
  2616. /// <typeparam name="TSource">The type of elements of <paramref name="source"/>.</typeparam>
  2617. /// <param name="source">A sequence of values to determine the minimum value of.</param>
  2618. /// <param name="selector">A transform function to apply to each element.</param>
  2619. /// <returns>The minimum value in the sequence.</returns>
  2620. /// <exception cref="T:System.ArgumentNullException">
  2621. /// <paramref name="source"/> or <paramref name="selector"/> is a null reference (Nothing in Visual Basic).
  2622. /// </exception>
  2623. /// <exception cref="T:System.AggregateException">
  2624. /// One or more exceptions occurred during the evaluation of the query.
  2625. /// </exception>
  2626. /// <exception cref="T:System.OperationCanceledException">
  2627. /// The query was canceled.
  2628. /// </exception>
  2629. public static long? Min<TSource>(this ParallelQuery<TSource> source, Func<TSource, long?> selector)
  2630. {
  2631. return source.Select<TSource, long?>(selector).Min<long?>();
  2632. }
  2633. /// <summary>
  2634. /// Invokes in parallel a transform function on each element of a
  2635. /// sequence and returns the minimum value.
  2636. /// </summary>
  2637. /// <typeparam name="TSource">The type of elements of <paramref name="source"/>.</typeparam>
  2638. /// <param name="source">A sequence of values to determine the minimum value of.</param>
  2639. /// <param name="selector">A transform function to apply to each element.</param>
  2640. /// <returns>The minimum value in the sequence.</returns>
  2641. /// <exception cref="T:System.ArgumentNullException">
  2642. /// <paramref name="source"/> or <paramref name="selector"/> is a null reference (Nothing in Visual Basic).
  2643. /// </exception>
  2644. /// <exception cref="T:System.InvalidOperationException">
  2645. /// <paramref name="source"/> contains no elements.
  2646. /// </exception>
  2647. /// <exception cref="T:System.AggregateException">
  2648. /// One or more exceptions occurred during the evaluation of the query.
  2649. /// </exception>
  2650. /// <exception cref="T:System.OperationCanceledException">
  2651. /// The query was canceled.
  2652. /// </exception>
  2653. public static float Min<TSource>(this ParallelQuery<TSource> source, Func<TSource, float> selector)
  2654. {
  2655. return source.Select<TSource, float>(selector).Min<float>();
  2656. }
  2657. /// <summary>
  2658. /// Invokes in parallel a transform function on each element of a
  2659. /// sequence and returns the minimum value.
  2660. /// </summary>
  2661. /// <typeparam name="TSource">The type of elements of <paramref name="source"/>.</typeparam>
  2662. /// <param name="source">A sequence of values to determine the minimum value of.</param>
  2663. /// <param name="selector">A transform function to apply to each element.</param>
  2664. /// <returns>The minimum value in the sequence.</returns>
  2665. /// <exception cref="T:System.ArgumentNullException">
  2666. /// <paramref name="source"/> or <paramref name="selector"/> is a null reference (Nothing in Visual Basic).
  2667. /// </exception>
  2668. /// <exception cref="T:System.AggregateException">
  2669. /// One or more exceptions occurred during the evaluation of the query.
  2670. /// </exception>
  2671. /// <exception cref="T:System.OperationCanceledException">
  2672. /// The query was canceled.
  2673. /// </exception>
  2674. public static float? Min<TSource>(this ParallelQuery<TSource> source, Func<TSource, float?> selector)
  2675. {
  2676. return source.Select<TSource, float?>(selector).Min<float?>();
  2677. }
  2678. /// <summary>
  2679. /// Invokes in parallel a transform function on each element of a
  2680. /// sequence and returns the minimum value.
  2681. /// </summary>
  2682. /// <typeparam name="TSource">The type of elements of <paramref name="source"/>.</typeparam>
  2683. /// <param name="source">A sequence of values to determine the minimum value of.</param>
  2684. /// <param name="selector">A transform function to apply to each element.</param>
  2685. /// <returns>The minimum value in the sequence.</returns>
  2686. /// <exception cref="T:System.ArgumentNullException">
  2687. /// <paramref name="source"/> or <paramref name="selector"/> is a null reference (Nothing in Visual Basic).
  2688. /// </exception>
  2689. /// <exception cref="T:System.InvalidOperationException">
  2690. /// <paramref name="source"/> contains no elements.
  2691. /// </exception>
  2692. /// <exception cref="T:System.AggregateException">
  2693. /// One or more exceptions occurred during the evaluation of the query.
  2694. /// </exception>
  2695. /// <exception cref="T:System.OperationCanceledException">
  2696. /// The query was canceled.
  2697. /// </exception>
  2698. public static double Min<TSource>(this ParallelQuery<TSource> source, Func<TSource, double> selector)
  2699. {
  2700. return source.Select<TSource, double>(selector).Min<double>();
  2701. }
  2702. /// <summary>
  2703. /// Invokes in parallel a transform function on each element of a
  2704. /// sequence and returns the minimum value.
  2705. /// </summary>
  2706. /// <typeparam name="TSource">The type of elements of <paramref name="source"/>.</typeparam>
  2707. /// <param name="source">A sequence of values to determine the minimum value of.</param>
  2708. /// <param name="selector">A transform function to apply to each element.</param>
  2709. /// <returns>The minimum value in the sequence.</returns>
  2710. /// <exception cref="T:System.ArgumentNullException">
  2711. /// <paramref name="source"/> or <paramref name="selector"/> is a null reference (Nothing in Visual Basic).
  2712. /// </exception>
  2713. /// <exception cref="T:System.AggregateException">
  2714. /// One or more exceptions occurred during the evaluation of the query.
  2715. /// </exception>
  2716. /// <exception cref="T:System.OperationCanceledException">
  2717. /// The query was canceled.
  2718. /// </exception>
  2719. public static double? Min<TSource>(this ParallelQuery<TSource> source, Func<TSource, double?> selector)
  2720. {
  2721. return source.Select<TSource, double?>(selector).Min<double?>();
  2722. }
  2723. /// <summary>
  2724. /// Invokes in parallel a transform function on each element of a
  2725. /// sequence and returns the minimum value.
  2726. /// </summary>
  2727. /// <typeparam name="TSource">The type of elements of <paramref name="source"/>.</typeparam>
  2728. /// <param name="source">A sequence of values to determine the minimum value of.</param>
  2729. /// <param name="selector">A transform function to apply to each element.</param>
  2730. /// <returns>The minimum value in the sequence.</returns>
  2731. /// <exception cref="T:System.ArgumentNullException">
  2732. /// <paramref name="source"/> or <paramref name="selector"/> is a null reference (Nothing in Visual Basic).
  2733. /// </exception>
  2734. /// <exception cref="T:System.InvalidOperationException">
  2735. /// <paramref name="source"/> contains no elements.
  2736. /// </exception>
  2737. /// <exception cref="T:System.AggregateException">
  2738. /// One or more exceptions occurred during the evaluation of the query.
  2739. /// </exception>
  2740. /// <exception cref="T:System.OperationCanceledException">
  2741. /// The query was canceled.
  2742. /// </exception>
  2743. public static decimal Min<TSource>(this ParallelQuery<TSource> source, Func<TSource, decimal> selector)
  2744. {
  2745. return source.Select<TSource, decimal>(selector).Min<decimal>();
  2746. }
  2747. /// <summary>
  2748. /// Invokes in parallel a transform function on each element of a
  2749. /// sequence and returns the minimum value.
  2750. /// </summary>
  2751. /// <typeparam name="TSource">The type of elements of <paramref name="source"/>.</typeparam>
  2752. /// <param name="source">A sequence of values to determine the minimum value of.</param>
  2753. /// <param name="selector">A transform function to apply to each element.</param>
  2754. /// <returns>The minimum value in the sequence.</returns>
  2755. /// <exception cref="T:System.ArgumentNullException">
  2756. /// <paramref name="source"/> or <paramref name="selector"/> is a null reference (Nothing in Visual Basic).
  2757. /// </exception>
  2758. /// <exception cref="T:System.AggregateException">
  2759. /// One or more exceptions occurred during the evaluation of the query.
  2760. /// </exception>
  2761. /// <exception cref="T:System.OperationCanceledException">
  2762. /// The query was canceled.
  2763. /// </exception>
  2764. public static decimal? Min<TSource>(this ParallelQuery<TSource> source, Func<TSource, decimal?> selector)
  2765. {
  2766. return source.Select<TSource, decimal?>(selector).Min<decimal?>();
  2767. }
  2768. /// <summary>
  2769. /// Invokes in parallel a transform function on each element of a
  2770. /// sequence and returns the minimum value.
  2771. /// </summary>
  2772. /// <typeparam name="TSource">The type of elements of <paramref name="source"/>.</typeparam>
  2773. /// <typeparam name="TResult">The type of the value returned by <paramref name="selector"/>.</typeparam>
  2774. /// <param name="source">A sequence of values to determine the minimum value of.</param>
  2775. /// <param name="selector">A transform function to apply to each element.</param>
  2776. /// <returns>The minimum value in the sequence.</returns>
  2777. /// <exception cref="T:System.ArgumentNullException">
  2778. /// <paramref name="source"/> or <paramref name="selector"/> is a null reference (Nothing in Visual Basic).
  2779. /// </exception>
  2780. /// <exception cref="T:System.InvalidOperationException">
  2781. /// <paramref name="source"/> contains no elements and <typeparamref name="TResult"/> is a non-nullable value type.
  2782. /// </exception>
  2783. /// <exception cref="T:System.AggregateException">
  2784. /// One or more exceptions occurred during the evaluation of the query.
  2785. /// </exception>
  2786. /// <exception cref="T:System.OperationCanceledException">
  2787. /// The query was canceled.
  2788. /// </exception>
  2789. public static TResult Min<TSource, TResult>(this ParallelQuery<TSource> source, Func<TSource, TResult> selector)
  2790. {
  2791. return source.Select<TSource, TResult>(selector).Min<TResult>();
  2792. }
  2793. //-----------------------------------------------------------------------------------
  2794. // Max aggregations.
  2795. //
  2796. /// <summary>
  2797. /// Returns the maximum value in a parallel sequence of values.
  2798. /// </summary>
  2799. /// <param name="source">A sequence of values to determine the maximum value of.</param>
  2800. /// <returns>The maximum value in the sequence.</returns>
  2801. /// <exception cref="T:System.ArgumentNullException">
  2802. /// <paramref name="source"/> is a null reference (Nothing in Visual Basic).
  2803. /// </exception>
  2804. /// <exception cref="T:System.InvalidOperationException">
  2805. /// <paramref name="source"/> contains no elements.
  2806. /// </exception>
  2807. /// <exception cref="T:System.AggregateException">
  2808. /// One or more exceptions occurred during the evaluation of the query.
  2809. /// </exception>
  2810. /// <exception cref="T:System.OperationCanceledException">
  2811. /// The query was canceled.
  2812. /// </exception>
  2813. public static int Max(this ParallelQuery<int> source)
  2814. {
  2815. if (source == null) throw new ArgumentNullException("source");
  2816. return new IntMinMaxAggregationOperator(source, 1).Aggregate();
  2817. }
  2818. /// <summary>
  2819. /// Returns the maximum value in a parallel sequence of values.
  2820. /// </summary>
  2821. /// <param name="source">A sequence of values to determine the maximum value of.</param>
  2822. /// <returns>The maximum value in the sequence.</returns>
  2823. /// <exception cref="T:System.ArgumentNullException">
  2824. /// <paramref name="source"/> is a null reference (Nothing in Visual Basic).
  2825. /// </exception>
  2826. /// <exception cref="T:System.AggregateException">
  2827. /// One or more exceptions occurred during the evaluation of the query.
  2828. /// </exception>
  2829. /// <exception cref="T:System.OperationCanceledException">
  2830. /// The query was canceled.
  2831. /// </exception>
  2832. public static int? Max(this ParallelQuery<int?> source)
  2833. {
  2834. if (source == null) throw new ArgumentNullException("source");
  2835. return new NullableIntMinMaxAggregationOperator(source, 1).Aggregate();
  2836. }
  2837. /// <summary>
  2838. /// Returns the maximum value in a parallel sequence of values.
  2839. /// </summary>
  2840. /// <param name="source">A sequence of values to determine the maximum value of.</param>
  2841. /// <returns>The maximum value in the sequence.</returns>
  2842. /// <exception cref="T:System.ArgumentNullException">
  2843. /// <paramref name="source"/> is a null reference (Nothing in Visual Basic).
  2844. /// </exception>
  2845. /// <exception cref="T:System.InvalidOperationException">
  2846. /// <paramref name="source"/> contains no elements.
  2847. /// </exception>
  2848. /// <exception cref="T:System.AggregateException">
  2849. /// One or more exceptions occurred during the evaluation of the query.
  2850. /// </exception>
  2851. /// <exception cref="T:System.OperationCanceledException">
  2852. /// The query was canceled.
  2853. /// </exception>
  2854. public static long Max(this ParallelQuery<long> source)
  2855. {
  2856. if (source == null) throw new ArgumentNullException("source");
  2857. return new LongMinMaxAggregationOperator(source, 1).Aggregate();
  2858. }
  2859. /// <summary>
  2860. /// Returns the maximum value in a parallel sequence of values.
  2861. /// </summary>
  2862. /// <param name="source">A sequence of values to determine the maximum value of.</param>
  2863. /// <returns>The maximum value in the sequence.</returns>
  2864. /// <exception cref="T:System.ArgumentNullException">
  2865. /// <paramref name="source"/> is a null reference (Nothing in Visual Basic).
  2866. /// </exception>
  2867. /// <exception cref="T:System.AggregateException">
  2868. /// One or more exceptions occurred during the evaluation of the query.
  2869. /// </exception>
  2870. /// <exception cref="T:System.OperationCanceledException">
  2871. /// The query was canceled.
  2872. /// </exception>
  2873. public static long? Max(this ParallelQuery<long?> source)
  2874. {
  2875. if (source == null) throw new ArgumentNullException("source");
  2876. return new NullableLongMinMaxAggregationOperator(source, 1).Aggregate();
  2877. }
  2878. /// <summary>
  2879. /// Returns the maximum value in a parallel sequence of values.
  2880. /// </summary>
  2881. /// <param name="source">A sequence of values to determine the maximum value of.</param>
  2882. /// <returns>The maximum value in the sequence.</returns>
  2883. /// <exception cref="T:System.ArgumentNullException">
  2884. /// <paramref name="source"/> is a null reference (Nothing in Visual Basic).
  2885. /// </exception>
  2886. /// <exception cref="T:System.InvalidOperationException">
  2887. /// <paramref name="source"/> contains no elements.
  2888. /// </exception>
  2889. /// <exception cref="T:System.AggregateException">
  2890. /// One or more exceptions occurred during the evaluation of the query.
  2891. /// </exception>
  2892. /// <exception cref="T:System.OperationCanceledException">
  2893. /// The query was canceled.
  2894. /// </exception>
  2895. public static float Max(this ParallelQuery<float> source)
  2896. {
  2897. if (source == null) throw new ArgumentNullException("source");
  2898. return new FloatMinMaxAggregationOperator(source, 1).Aggregate();
  2899. }
  2900. /// <summary>
  2901. /// Returns the maximum value in a parallel sequence of values.
  2902. /// </summary>
  2903. /// <param name="source">A sequence of values to determine the maximum value of.</param>
  2904. /// <returns>The maximum value in the sequence.</returns>
  2905. /// <exception cref="T:System.ArgumentNullException">
  2906. /// <paramref name="source"/> is a null reference (Nothing in Visual Basic).
  2907. /// </exception>
  2908. /// <exception cref="T:System.AggregateException">
  2909. /// One or more exceptions occurred during the evaluation of the query.
  2910. /// </exception>
  2911. /// <exception cref="T:System.OperationCanceledException">
  2912. /// The query was canceled.
  2913. /// </exception>
  2914. public static float? Max(this ParallelQuery<float?> source)
  2915. {
  2916. if (source == null) throw new ArgumentNullException("source");
  2917. return new NullableFloatMinMaxAggregationOperator(source, 1).Aggregate();
  2918. }
  2919. /// <summary>
  2920. /// Returns the maximum value in a parallel sequence of values.
  2921. /// </summary>
  2922. /// <param name="source">A sequence of values to determine the maximum value of.</param>
  2923. /// <returns>The maximum value in the sequence.</returns>
  2924. /// <exception cref="T:System.ArgumentNullException">
  2925. /// <paramref name="source"/> is a null reference (Nothing in Visual Basic).
  2926. /// </exception>
  2927. /// <exception cref="T:System.InvalidOperationException">
  2928. /// <paramref name="source"/> contains no elements.
  2929. /// </exception>
  2930. /// <exception cref="T:System.AggregateException">
  2931. /// One or more exceptions occurred during the evaluation of the query.
  2932. /// </exception>
  2933. /// <exception cref="T:System.OperationCanceledException">
  2934. /// The query was canceled.
  2935. /// </exception>
  2936. public static double Max(this ParallelQuery<double> source)
  2937. {
  2938. if (source == null) throw new ArgumentNullException("source");
  2939. return new DoubleMinMaxAggregationOperator(source, 1).Aggregate();
  2940. }
  2941. /// <summary>
  2942. /// Returns the maximum value in a parallel sequence of values.
  2943. /// </summary>
  2944. /// <param name="source">A sequence of values to determine the maximum value of.</param>
  2945. /// <returns>The maximum value in the sequence.</returns>
  2946. /// <exception cref="T:System.ArgumentNullException">
  2947. /// <paramref name="source"/> is a null reference (Nothing in Visual Basic).
  2948. /// </exception>
  2949. /// <exception cref="T:System.AggregateException">
  2950. /// One or more exceptions occurred during the evaluation of the query.
  2951. /// </exception>
  2952. /// <exception cref="T:System.OperationCanceledException">
  2953. /// The query was canceled.
  2954. /// </exception>
  2955. public static double? Max(this ParallelQuery<double?> source)
  2956. {
  2957. if (source == null) throw new ArgumentNullException("source");
  2958. return new NullableDoubleMinMaxAggregationOperator(source, 1).Aggregate();
  2959. }
  2960. /// <summary>
  2961. /// Returns the maximum value in a parallel sequence of values.
  2962. /// </summary>
  2963. /// <param name="source">A sequence of values to determine the maximum value of.</param>
  2964. /// <returns>The maximum value in the sequence.</returns>
  2965. /// <exception cref="T:System.ArgumentNullException">
  2966. /// <paramref name="source"/> is a null reference (Nothing in Visual Basic).
  2967. /// </exception>
  2968. /// <exception cref="T:System.InvalidOperationException">
  2969. /// <paramref name="source"/> contains no elements.
  2970. /// </exception>
  2971. /// <exception cref="T:System.AggregateException">
  2972. /// One or more exceptions occurred during the evaluation of the query.
  2973. /// </exception>
  2974. /// <exception cref="T:System.OperationCanceledException">
  2975. /// The query was canceled.
  2976. /// </exception>
  2977. public static decimal Max(this ParallelQuery<decimal> source)
  2978. {
  2979. if (source == null) throw new ArgumentNullException("source");
  2980. return new DecimalMinMaxAggregationOperator(source, 1).Aggregate();
  2981. }
  2982. /// <summary>
  2983. /// Returns the maximum value in a parallel sequence of values.
  2984. /// </summary>
  2985. /// <param name="source">A sequence of values to determine the maximum value of.</param>
  2986. /// <returns>The maximum value in the sequence.</returns>
  2987. /// <exception cref="T:System.ArgumentNullException">
  2988. /// <paramref name="source"/> is a null reference (Nothing in Visual Basic).
  2989. /// </exception>
  2990. /// <exception cref="T:System.AggregateException">
  2991. /// One or more exceptions occurred during the evaluation of the query.
  2992. /// </exception>
  2993. /// <exception cref="T:System.OperationCanceledException">
  2994. /// The query was canceled.
  2995. /// </exception>
  2996. public static decimal? Max(this ParallelQuery<decimal?> source)
  2997. {
  2998. if (source == null) throw new ArgumentNullException("source");
  2999. return new NullableDecimalMinMaxAggregationOperator(source, 1).Aggregate();
  3000. }
  3001. /// <summary>
  3002. /// Returns the maximum value in a parallel sequence of values.
  3003. /// </summary>
  3004. /// <param name="source">A sequence of values to determine the maximum value of.</param>
  3005. /// <returns>The maximum value in the sequence.</returns>
  3006. /// <exception cref="T:System.ArgumentNullException">
  3007. /// <paramref name="source"/> is a null reference (Nothing in Visual Basic).
  3008. /// </exception>
  3009. /// <exception cref="T:System.InvalidOperationException">
  3010. /// <paramref name="source"/> contains no elements and <typeparam name="TSource"/> is a non-nullable value type.
  3011. /// </exception>
  3012. /// <exception cref="T:System.AggregateException">
  3013. /// One or more exceptions occurred during the evaluation of the query.
  3014. /// </exception>
  3015. /// <exception cref="T:System.OperationCanceledException">
  3016. /// The query was canceled.
  3017. /// </exception>
  3018. public static TSource Max<TSource>(this ParallelQuery<TSource> source)
  3019. {
  3020. if (source == null) throw new ArgumentNullException("source");
  3021. return AggregationMinMaxHelpers<TSource>.ReduceMax(source);
  3022. }
  3023. /// <summary>
  3024. /// Invokes in parallel a transform function on each element of a
  3025. /// sequence and returns the maximum value.
  3026. /// </summary>
  3027. /// <typeparam name="TSource">The type of elements of <paramref name="source"/>.</typeparam>
  3028. /// <param name="source">A sequence of values to determine the maximum value of.</param>
  3029. /// <param name="selector">A transform function to apply to each element.</param>
  3030. /// <returns>The maximum value in the sequence.</returns>
  3031. /// <exception cref="T:System.ArgumentNullException">
  3032. /// <paramref name="source"/> or <paramref name="selector"/> is a null reference (Nothing in Visual Basic).
  3033. /// </exception>
  3034. /// <exception cref="T:System.InvalidOperationException">
  3035. /// <paramref name="source"/> contains no elements.
  3036. /// </exception>
  3037. /// <exception cref="T:System.AggregateException">
  3038. /// One or more exceptions occurred during the evaluation of the query.
  3039. /// </exception>
  3040. /// <exception cref="T:System.OperationCanceledException">
  3041. /// The query was canceled.
  3042. /// </exception>
  3043. public static int Max<TSource>(this ParallelQuery<TSource> source, Func<TSource, int> selector)
  3044. {
  3045. return source.Select<TSource, int>(selector).Max<int>();
  3046. }
  3047. /// <summary>
  3048. /// Invokes in parallel a transform function on each element of a
  3049. /// sequence and returns the maximum value.
  3050. /// </summary>
  3051. /// <typeparam name="TSource">The type of elements of <paramref name="source"/>.</typeparam>
  3052. /// <param name="source">A sequence of values to determine the maximum value of.</param>
  3053. /// <param name="selector">A transform function to apply to each element.</param>
  3054. /// <returns>The maximum value in the sequence.</returns>
  3055. /// <exception cref="T:System.ArgumentNullException">
  3056. /// <paramref name="source"/> or <paramref name="selector"/> is a null reference (Nothing in Visual Basic).
  3057. /// </exception>
  3058. /// <exception cref="T:System.AggregateException">
  3059. /// One or more exceptions occurred during the evaluation of the query.
  3060. /// </exception>
  3061. /// <exception cref="T:System.OperationCanceledException">
  3062. /// The query was canceled.
  3063. /// </exception>
  3064. public static int? Max<TSource>(this ParallelQuery<TSource> source, Func<TSource, int?> selector)
  3065. {
  3066. return source.Select<TSource, int?>(selector).Max<int?>();
  3067. }
  3068. /// <summary>
  3069. /// Invokes in parallel a transform function on each element of a
  3070. /// sequence and returns the maximum value.
  3071. /// </summary>
  3072. /// <typeparam name="TSource">The type of elements of <paramref name="source"/>.</typeparam>
  3073. /// <param name="source">A sequence of values to determine the maximum value of.</param>
  3074. /// <param name="selector">A transform function to apply to each element.</param>
  3075. /// <returns>The maximum value in the sequence.</returns>
  3076. /// <exception cref="T:System.ArgumentNullException">
  3077. /// <paramref name="source"/> or <paramref name="selector"/> is a null reference (Nothing in Visual Basic).
  3078. /// </exception>
  3079. /// <exception cref="T:System.InvalidOperationException">
  3080. /// <paramref name="source"/> contains no elements.
  3081. /// </exception>
  3082. /// <exception cref="T:System.AggregateException">
  3083. /// One or more exceptions occurred during the evaluation of the query.
  3084. /// </exception>
  3085. /// <exception cref="T:System.OperationCanceledException">
  3086. /// The query was canceled.
  3087. /// </exception>
  3088. public static long Max<TSource>(this ParallelQuery<TSource> source, Func<TSource, long> selector)
  3089. {
  3090. return source.Select<TSource, long>(selector).Max<long>();
  3091. }
  3092. /// <summary>
  3093. /// Invokes in parallel a transform function on each element of a
  3094. /// sequence and returns the maximum value.
  3095. /// </summary>
  3096. /// <typeparam name="TSource">The type of elements of <paramref name="source"/>.</typeparam>
  3097. /// <param name="source">A sequence of values to determine the maximum value of.</param>
  3098. /// <param name="selector">A transform function to apply to each element.</param>
  3099. /// <returns>The maximum value in the sequence.</returns>
  3100. /// <exception cref="T:System.ArgumentNullException">
  3101. /// <paramref name="source"/> or <paramref name="selector"/> is a null reference (Nothing in Visual Basic).
  3102. /// </exception>
  3103. /// <exception cref="T:System.AggregateException">
  3104. /// One or more exceptions occurred during the evaluation of the query.
  3105. /// </exception>
  3106. /// <exception cref="T:System.OperationCanceledException">
  3107. /// The query was canceled.
  3108. /// </exception>
  3109. public static long? Max<TSource>(this ParallelQuery<TSource> source, Func<TSource, long?> selector)
  3110. {
  3111. return source.Select<TSource, long?>(selector).Max<long?>();
  3112. }
  3113. /// <summary>
  3114. /// Invokes in parallel a transform function on each element of a
  3115. /// sequence and returns the maximum value.
  3116. /// </summary>
  3117. /// <typeparam name="TSource">The type of elements of <paramref name="source"/>.</typeparam>
  3118. /// <param name="source">A sequence of values to determine the maximum value of.</param>
  3119. /// <param name="selector">A transform function to apply to each element.</param>
  3120. /// <returns>The maximum value in the sequence.</returns>
  3121. /// <exception cref="T:System.ArgumentNullException">
  3122. /// <paramref name="source"/> or <paramref name="selector"/> is a null reference (Nothing in Visual Basic).
  3123. /// </exception>
  3124. /// <exception cref="T:System.InvalidOperationException">
  3125. /// <paramref name="source"/> contains no elements.
  3126. /// </exception>
  3127. /// <exception cref="T:System.AggregateException">
  3128. /// One or more exceptions occurred during the evaluation of the query.
  3129. /// </exception>
  3130. /// <exception cref="T:System.OperationCanceledException">
  3131. /// The query was canceled.
  3132. /// </exception>
  3133. public static float Max<TSource>(this ParallelQuery<TSource> source, Func<TSource, float> selector)
  3134. {
  3135. return source.Select<TSource, float>(selector).Max<float>();
  3136. }
  3137. /// <summary>
  3138. /// Invokes in parallel a transform function on each element of a
  3139. /// sequence and returns the maximum value.
  3140. /// </summary>
  3141. /// <typeparam name="TSource">The type of elements of <paramref name="source"/>.</typeparam>
  3142. /// <param name="source">A sequence of values to determine the maximum value of.</param>
  3143. /// <param name="selector">A transform function to apply to each element.</param>
  3144. /// <returns>The maximum value in the sequence.</returns>
  3145. /// <exception cref="T:System.ArgumentNullException">
  3146. /// <paramref name="source"/> or <paramref name="selector"/> is a null reference (Nothing in Visual Basic).
  3147. /// </exception>
  3148. /// <exception cref="T:System.AggregateException">
  3149. /// One or more exceptions occurred during the evaluation of the query.
  3150. /// </exception>
  3151. /// <exception cref="T:System.OperationCanceledException">
  3152. /// The query was canceled.
  3153. /// </exception>
  3154. public static float? Max<TSource>(this ParallelQuery<TSource> source, Func<TSource, float?> selector)
  3155. {
  3156. return source.Select<TSource, float?>(selector).Max<float?>();
  3157. }
  3158. /// <summary>
  3159. /// Invokes in parallel a transform function on each element of a
  3160. /// sequence and returns the maximum value.
  3161. /// </summary>
  3162. /// <typeparam name="TSource">The type of elements of <paramref name="source"/>.</typeparam>
  3163. /// <param name="source">A sequence of values to determine the maximum value of.</param>
  3164. /// <param name="selector">A transform function to apply to each element.</param>
  3165. /// <returns>The maximum value in the sequence.</returns>
  3166. /// <exception cref="T:System.ArgumentNullException">
  3167. /// <paramref name="source"/> or <paramref name="selector"/> is a null reference (Nothing in Visual Basic).
  3168. /// </exception>
  3169. /// <exception cref="T:System.InvalidOperationException">
  3170. /// <paramref name="source"/> contains no elements.
  3171. /// </exception>
  3172. /// <exception cref="T:System.AggregateException">
  3173. /// One or more exceptions occurred during the evaluation of the query.
  3174. /// </exception>
  3175. /// <exception cref="T:System.OperationCanceledException">
  3176. /// The query was canceled.
  3177. /// </exception>
  3178. public static double Max<TSource>(this ParallelQuery<TSource> source, Func<TSource, double> selector)
  3179. {
  3180. return source.Select<TSource, double>(selector).Max<double>();
  3181. }
  3182. /// <summary>
  3183. /// Invokes in parallel a transform function on each element of a
  3184. /// sequence and returns the maximum value.
  3185. /// </summary>
  3186. /// <typeparam name="TSource">The type of elements of <paramref name="source"/>.</typeparam>
  3187. /// <param name="source">A sequence of values to determine the maximum value of.</param>
  3188. /// <param name="selector">A transform function to apply to each element.</param>
  3189. /// <returns>The maximum value in the sequence.</returns>
  3190. /// <exception cref="T:System.ArgumentNullException">
  3191. /// <paramref name="source"/> or <paramref name="selector"/> is a null reference (Nothing in Visual Basic).
  3192. /// </exception>
  3193. /// <exception cref="T:System.AggregateException">
  3194. /// One or more exceptions occurred during the evaluation of the query.
  3195. /// </exception>
  3196. /// <exception cref="T:System.OperationCanceledException">
  3197. /// The query was canceled.
  3198. /// </exception>
  3199. public static double? Max<TSource>(this ParallelQuery<TSource> source, Func<TSource, double?> selector)
  3200. {
  3201. return source.Select<TSource, double?>(selector).Max<double?>();
  3202. }
  3203. /// <summary>
  3204. /// Invokes in parallel a transform function on each element of a
  3205. /// sequence and returns the maximum value.
  3206. /// </summary>
  3207. /// <typeparam name="TSource">The type of elements of <paramref name="source"/>.</typeparam>
  3208. /// <param name="source">A sequence of values to determine the maximum value of.</param>
  3209. /// <param name="selector">A transform function to apply to each element.</param>
  3210. /// <returns>The maximum value in the sequence.</returns>
  3211. /// <exception cref="T:System.ArgumentNullException">
  3212. /// <paramref name="source"/> or <paramref name="selector"/> is a null reference (Nothing in Visual Basic).
  3213. /// </exception>
  3214. /// <exception cref="T:System.InvalidOperationException">
  3215. /// <paramref name="source"/> contains no elements.
  3216. /// </exception>
  3217. /// <exception cref="T:System.AggregateException">
  3218. /// One or more exceptions occurred during the evaluation of the query.
  3219. /// </exception>
  3220. /// <exception cref="T:System.OperationCanceledException">
  3221. /// The query was canceled.
  3222. /// </exception>
  3223. public static decimal Max<TSource>(this ParallelQuery<TSource> source, Func<TSource, decimal> selector)
  3224. {
  3225. return source.Select<TSource, decimal>(selector).Max<decimal>();
  3226. }
  3227. /// <summary>
  3228. /// Invokes in parallel a transform function on each element of a
  3229. /// sequence and returns the maximum value.
  3230. /// </summary>
  3231. /// <typeparam name="TSource">The type of elements of <paramref name="source"/>.</typeparam>
  3232. /// <param name="source">A sequence of values to determine the maximum value of.</param>
  3233. /// <param name="selector">A transform function to apply to each element.</param>
  3234. /// <returns>The maximum value in the sequence.</returns>
  3235. /// <exception cref="T:System.ArgumentNullException">
  3236. /// <paramref name="source"/> or <paramref name="selector"/> is a null reference (Nothing in Visual Basic).
  3237. /// </exception>
  3238. /// <exception cref="T:System.AggregateException">
  3239. /// One or more exceptions occurred during the evaluation of the query.
  3240. /// </exception>
  3241. /// <exception cref="T:System.OperationCanceledException">
  3242. /// The query was canceled.
  3243. /// </exception>
  3244. public static decimal? Max<TSource>(this ParallelQuery<TSource> source, Func<TSource, decimal?> selector)
  3245. {
  3246. return source.Select<TSource, decimal?>(selector).Max<decimal?>();
  3247. }
  3248. /// <summary>
  3249. /// Invokes in parallel a transform function on each element of a
  3250. /// sequence and returns the maximum value.
  3251. /// </summary>
  3252. /// <typeparam name="TSource">The type of elements of <paramref name="source"/>.</typeparam>
  3253. /// <typeparam name="TResult">The type of the value returned by <paramref name="selector"/>.</typeparam>
  3254. /// <param name="source">A sequence of values to determine the maximum value of.</param>
  3255. /// <param name="selector">A transform function to apply to each element.</param>
  3256. /// <returns>The maximum value in the sequence.</returns>
  3257. /// <exception cref="T:System.ArgumentNullException">
  3258. /// <paramref name="source"/> or <paramref name="selector"/> is a null reference (Nothing in Visual Basic).
  3259. /// </exception>
  3260. /// <exception cref="T:System.InvalidOperationException">
  3261. /// <paramref name="source"/> contains no elements and <typeparamref name="TResult"/> is a non-nullable value type.
  3262. /// </exception>
  3263. /// <exception cref="T:System.AggregateException">
  3264. /// One or more exceptions occurred during the evaluation of the query.
  3265. /// </exception>
  3266. /// <exception cref="T:System.OperationCanceledException">
  3267. /// The query was canceled.
  3268. /// </exception>
  3269. public static TResult Max<TSource, TResult>(this ParallelQuery<TSource> source, Func<TSource, TResult> selector)
  3270. {
  3271. return source.Select<TSource, TResult>(selector).Max<TResult>();
  3272. }
  3273. //-----------------------------------------------------------------------------------
  3274. // Average aggregations.
  3275. //
  3276. /// <summary>
  3277. /// Computes in parallel the average of a sequence of values.
  3278. /// </summary>
  3279. /// <param name="source">A sequence of values that are used to calculate an average.</param>
  3280. /// <returns>The average of the sequence of values.</returns>
  3281. /// <exception cref="T:System.ArgumentNullException">
  3282. /// <paramref name="source"/> is a null reference (Nothing in Visual Basic).
  3283. /// </exception>
  3284. /// <exception cref="T:System.InvalidOperationException">
  3285. /// <paramref name="source"/> contains no elements.
  3286. /// </exception>
  3287. /// <exception cref="T:System.AggregateException">
  3288. /// The sum or count of the elements in the sequence is larger than <see cref="M:System.Int32.MaxValue"/>.
  3289. /// -or-
  3290. /// One or more exceptions occurred during the evaluation of the query.
  3291. /// </exception>
  3292. /// <exception cref="T:System.OperationCanceledException">
  3293. /// The query was canceled.
  3294. /// </exception>
  3295. public static double Average(this ParallelQuery<int> source)
  3296. {
  3297. if (source == null) throw new ArgumentNullException("source");
  3298. return new IntAverageAggregationOperator(source).Aggregate();
  3299. }
  3300. /// <summary>
  3301. /// Computes in parallel the average of a sequence of values.
  3302. /// </summary>
  3303. /// <param name="source">A sequence of values that are used to calculate an average.</param>
  3304. /// <returns>The average of the sequence of values.</returns>
  3305. /// <exception cref="T:System.ArgumentNullException">
  3306. /// <paramref name="source"/> is a null reference (Nothing in Visual Basic).
  3307. /// </exception>
  3308. /// <exception cref="T:System.AggregateException">
  3309. /// The sum or count of the elements in the sequence is larger than <see cref="M:System.Int32.MaxValue"/>.
  3310. /// -or-
  3311. /// One or more exceptions occurred during the evaluation of the query.
  3312. /// </exception>
  3313. /// <exception cref="T:System.OperationCanceledException">
  3314. /// The query was canceled.
  3315. /// </exception>
  3316. public static double? Average(this ParallelQuery<int?> source)
  3317. {
  3318. if (source == null) throw new ArgumentNullException("source");
  3319. return new NullableIntAverageAggregationOperator(source).Aggregate();
  3320. }
  3321. /// <summary>
  3322. /// Computes in parallel the average of a sequence of values.
  3323. /// </summary>
  3324. /// <param name="source">A sequence of values that are used to calculate an average.</param>
  3325. /// <returns>The average of the sequence of values.</returns>
  3326. /// <exception cref="T:System.ArgumentNullException">
  3327. /// <paramref name="source"/> is a null reference (Nothing in Visual Basic).
  3328. /// </exception>
  3329. /// <exception cref="T:System.InvalidOperationException">
  3330. /// <paramref name="source"/> contains no elements.
  3331. /// </exception>
  3332. /// <exception cref="T:System.AggregateException">
  3333. /// The sum or count of the elements in the sequence is larger than <see cref="M:System.Int32.MaxValue"/>.
  3334. /// -or-
  3335. /// One or more exceptions occurred during the evaluation of the query.
  3336. /// </exception>
  3337. /// <exception cref="T:System.OperationCanceledException">
  3338. /// The query was canceled.
  3339. /// </exception>
  3340. public static double Average(this ParallelQuery<long> source)
  3341. {
  3342. if (source == null) throw new ArgumentNullException("source");
  3343. return new LongAverageAggregationOperator(source).Aggregate();
  3344. }
  3345. /// <summary>
  3346. /// Computes in parallel the average of a sequence of values.
  3347. /// </summary>
  3348. /// <param name="source">A sequence of values that are used to calculate an average.</param>
  3349. /// <returns>The average of the sequence of values.</returns>
  3350. /// <exception cref="T:System.ArgumentNullException">
  3351. /// <paramref name="source"/> is a null reference (Nothing in Visual Basic).
  3352. /// </exception>
  3353. /// <exception cref="T:System.AggregateException">
  3354. /// The sum or count of the elements in the sequence is larger than <see cref="M:System.Int32.MaxValue"/>.
  3355. /// -or-
  3356. /// One or more exceptions occurred during the evaluation of the query.
  3357. /// </exception>
  3358. /// <exception cref="T:System.OperationCanceledException">
  3359. /// The query was canceled.
  3360. /// </exception>
  3361. public static double? Average(this ParallelQuery<long?> source)
  3362. {
  3363. if (source == null) throw new ArgumentNullException("source");
  3364. return new NullableLongAverageAggregationOperator(source).Aggregate();
  3365. }
  3366. /// <summary>
  3367. /// Computes in parallel the average of a sequence of values.
  3368. /// </summary>
  3369. /// <param name="source">A sequence of values that are used to calculate an average.</param>
  3370. /// <returns>The average of the sequence of values.</returns>
  3371. /// <exception cref="T:System.ArgumentNullException">
  3372. /// <paramref name="source"/> is a null reference (Nothing in Visual Basic).
  3373. /// </exception>
  3374. /// <exception cref="T:System.InvalidOperationException">
  3375. /// <paramref name="source"/> contains no elements.
  3376. /// </exception>
  3377. /// <exception cref="T:System.AggregateException">
  3378. /// One or more exceptions occurred during the evaluation of the query.
  3379. /// </exception>
  3380. /// <exception cref="T:System.OperationCanceledException">
  3381. /// The query was canceled.
  3382. /// </exception>
  3383. public static float Average(this ParallelQuery<float> source)
  3384. {
  3385. if (source == null) throw new ArgumentNullException("source");
  3386. return new FloatAverageAggregationOperator(source).Aggregate();
  3387. }
  3388. /// <summary>
  3389. /// Computes in parallel the average of a sequence of values.
  3390. /// </summary>
  3391. /// <param name="source">A sequence of values that are used to calculate an average.</param>
  3392. /// <returns>The average of the sequence of values.</returns>
  3393. /// <exception cref="T:System.ArgumentNullException">
  3394. /// <paramref name="source"/> is a null reference (Nothing in Visual Basic).
  3395. /// </exception>
  3396. /// <exception cref="T:System.AggregateException">
  3397. /// One or more exceptions occurred during the evaluation of the query.
  3398. /// </exception>
  3399. /// <exception cref="T:System.OperationCanceledException">
  3400. /// The query was canceled.
  3401. /// </exception>
  3402. public static float? Average(this ParallelQuery<float?> source)
  3403. {
  3404. if (source == null) throw new ArgumentNullException("source");
  3405. return new NullableFloatAverageAggregationOperator(source).Aggregate();
  3406. }
  3407. /// <summary>
  3408. /// Computes in parallel the average of a sequence of values.
  3409. /// </summary>
  3410. /// <param name="source">A sequence of values that are used to calculate an average.</param>
  3411. /// <returns>The average of the sequence of values.</returns>
  3412. /// <exception cref="T:System.ArgumentNullException">
  3413. /// <paramref name="source"/> is a null reference (Nothing in Visual Basic).
  3414. /// </exception>
  3415. /// <exception cref="T:System.InvalidOperationException">
  3416. /// <paramref name="source"/> contains no elements.
  3417. /// </exception>
  3418. /// <exception cref="T:System.AggregateException">
  3419. /// One or more exceptions occurred during the evaluation of the query.
  3420. /// </exception>
  3421. /// <exception cref="T:System.OperationCanceledException">
  3422. /// The query was canceled.
  3423. /// </exception>
  3424. public static double Average(this ParallelQuery<double> source)
  3425. {
  3426. if (source == null) throw new ArgumentNullException("source");
  3427. return new DoubleAverageAggregationOperator(source).Aggregate();
  3428. }
  3429. /// <summary>
  3430. /// Computes in parallel the average of a sequence of values.
  3431. /// </summary>
  3432. /// <exception cref="T:System.ArgumentNullException">
  3433. /// <param name="source">A sequence of values that are used to calculate an average.</param>
  3434. /// <returns>The average of the sequence of values.</returns>
  3435. /// <paramref name="source"/> is a null reference (Nothing in Visual Basic).
  3436. /// </exception>
  3437. /// <exception cref="T:System.AggregateException">
  3438. /// One or more exceptions occurred during the evaluation of the query.
  3439. /// </exception>
  3440. /// <exception cref="T:System.OperationCanceledException">
  3441. /// The query was canceled.
  3442. /// </exception>
  3443. public static double? Average(this ParallelQuery<double?> source)
  3444. {
  3445. if (source == null) throw new ArgumentNullException("source");
  3446. return new NullableDoubleAverageAggregationOperator(source).Aggregate();
  3447. }
  3448. /// <summary>
  3449. /// Computes in parallel the average of a sequence of values.
  3450. /// </summary>
  3451. /// <param name="source">A sequence of values that are used to calculate an average.</param>
  3452. /// <returns>The average of the sequence of values.</returns>
  3453. /// <exception cref="T:System.ArgumentNullException">
  3454. /// <paramref name="source"/> is a null reference (Nothing in Visual Basic).
  3455. /// </exception>
  3456. /// <exception cref="T:System.InvalidOperationException">
  3457. /// <paramref name="source"/> contains no elements.
  3458. /// </exception>
  3459. /// <exception cref="T:System.AggregateException">
  3460. /// One or more exceptions occurred during the evaluation of the query.
  3461. /// </exception>
  3462. /// <exception cref="T:System.OperationCanceledException">
  3463. /// The query was canceled.
  3464. /// </exception>
  3465. public static decimal Average(this ParallelQuery<decimal> source)
  3466. {
  3467. if (source == null) throw new ArgumentNullException("source");
  3468. return new DecimalAverageAggregationOperator(source).Aggregate();
  3469. }
  3470. /// <summary>
  3471. /// Computes in parallel the average of a sequence of values.
  3472. /// </summary>
  3473. /// <param name="source">A sequence of values that are used to calculate an average.</param>
  3474. /// <returns>The average of the sequence of values.</returns>
  3475. /// <exception cref="T:System.ArgumentNullException">
  3476. /// <paramref name="source"/> is a null reference (Nothing in Visual Basic).
  3477. /// </exception>
  3478. /// <exception cref="T:System.AggregateException">
  3479. /// One or more exceptions occurred during the evaluation of the query.
  3480. /// </exception>
  3481. /// <exception cref="T:System.OperationCanceledException">
  3482. /// The query was canceled.
  3483. /// </exception>
  3484. public static decimal? Average(this ParallelQuery<decimal?> source)
  3485. {
  3486. if (source == null) throw new ArgumentNullException("source");
  3487. return new NullableDecimalAverageAggregationOperator(source).Aggregate();
  3488. }
  3489. /// <summary>
  3490. /// Computes in parallel the average of a sequence of values that are obtained
  3491. /// by invoking a transform function on each element of the input sequence.
  3492. /// </summary>
  3493. /// <typeparam name="TSource">The type of elements of <paramref name="source"/>.</typeparam>
  3494. /// <param name="source">A sequence of values that are used to calculate an average.</param>
  3495. /// <param name="selector">A transform function to apply to each element.</param>
  3496. /// <returns>The average of the sequence of values.</returns>
  3497. /// <exception cref="T:System.ArgumentNullException">
  3498. /// <paramref name="source"/> or <paramref name="selector"/> is a null reference (Nothing in Visual Basic).
  3499. /// </exception>
  3500. /// <exception cref="T:System.InvalidOperationException">
  3501. /// <paramref name="source"/> contains no elements.
  3502. /// </exception>
  3503. /// <exception cref="T:System.AggregateException">
  3504. /// The sum or count of the elements in the sequence is larger than <see cref="M:System.Int32.MaxValue"/>.
  3505. /// -or-
  3506. /// One or more exceptions occurred during the evaluation of the query.
  3507. /// </exception>
  3508. /// <exception cref="T:System.OperationCanceledException">
  3509. /// The query was canceled.
  3510. /// </exception>
  3511. public static double Average<TSource>(this ParallelQuery<TSource> source, Func<TSource, int> selector)
  3512. {
  3513. return source.Select(selector).Average();
  3514. }
  3515. /// <summary>
  3516. /// Computes in parallel the average of a sequence of values that are obtained
  3517. /// by invoking a transform function on each element of the input sequence.
  3518. /// </summary>
  3519. /// <typeparam name="TSource">The type of elements of <paramref name="source"/>.</typeparam>
  3520. /// <param name="source">A sequence of values that are used to calculate an average.</param>
  3521. /// <param name="selector">A transform function to apply to each element.</param>
  3522. /// <returns>The average of the sequence of values.</returns>
  3523. /// <exception cref="T:System.ArgumentNullException">
  3524. /// <paramref name="source"/> or <paramref name="selector"/> is a null reference (Nothing in Visual Basic).
  3525. /// </exception>
  3526. /// <exception cref="T:System.AggregateException">
  3527. /// The sum or count of the elements in the sequence is larger than <see cref="M:System.Int32.MaxValue"/>.
  3528. /// -or-
  3529. /// One or more exceptions occurred during the evaluation of the query.
  3530. /// </exception>
  3531. /// <exception cref="T:System.OperationCanceledException">
  3532. /// The query was canceled.
  3533. /// </exception>
  3534. public static double? Average<TSource>(this ParallelQuery<TSource> source, Func<TSource, int?> selector)
  3535. {
  3536. return source.Select(selector).Average();
  3537. }
  3538. /// <summary>
  3539. /// Computes in parallel the average of a sequence of values that are obtained
  3540. /// by invoking a transform function on each element of the input sequence.
  3541. /// </summary>
  3542. /// <typeparam name="TSource">The type of elements of <paramref name="source"/>.</typeparam>
  3543. /// <param name="source">A sequence of values that are used to calculate an average.</param>
  3544. /// <param name="selector">A transform function to apply to each element.</param>
  3545. /// <returns>The average of the sequence of values.</returns>
  3546. /// <exception cref="T:System.ArgumentNullException">
  3547. /// <paramref name="source"/> or <paramref name="selector"/> is a null reference (Nothing in Visual Basic).
  3548. /// </exception>
  3549. /// <exception cref="T:System.InvalidOperationException">
  3550. /// <paramref name="source"/> contains no elements.
  3551. /// </exception>
  3552. /// <exception cref="T:System.AggregateException">
  3553. /// The sum or count of the elements in the sequence is larger than <see cref="M:System.Int32.MaxValue"/>.
  3554. /// -or-
  3555. /// One or more exceptions occurred during the evaluation of the query.
  3556. /// </exception>
  3557. /// <exception cref="T:System.OperationCanceledException">
  3558. /// The query was canceled.
  3559. /// </exception>
  3560. public static double Average<TSource>(this ParallelQuery<TSource> source, Func<TSource, long> selector)
  3561. {
  3562. return source.Select(selector).Average();
  3563. }
  3564. /// <summary>
  3565. /// Computes in parallel the average of a sequence of values that are obtained
  3566. /// by invoking a transform function on each element of the input sequence.
  3567. /// </summary>
  3568. /// <typeparam name="TSource">The type of elements of <paramref name="source"/>.</typeparam>
  3569. /// <param name="source">A sequence of values that are used to calculate an average.</param>
  3570. /// <param name="selector">A transform function to apply to each element.</param>
  3571. /// <returns>The average of the sequence of values.</returns>
  3572. /// <exception cref="T:System.ArgumentNullException">
  3573. /// <paramref name="source"/> or <paramref name="selector"/> is a null reference (Nothing in Visual Basic).
  3574. /// </exception>
  3575. /// <exception cref="T:System.AggregateException">
  3576. /// The sum or count of the elements in the sequence is larger than <see cref="M:System.Int64.MaxValue"/>.
  3577. /// -or-
  3578. /// One or more exceptions occurred during the evaluation of the query.
  3579. /// </exception>
  3580. /// <exception cref="T:System.OperationCanceledException">
  3581. /// The query was canceled.
  3582. /// </exception>
  3583. public static double? Average<TSource>(this ParallelQuery<TSource> source, Func<TSource, long?> selector)
  3584. {
  3585. return source.Select(selector).Average();
  3586. }
  3587. /// <summary>
  3588. /// Computes in parallel the average of a sequence of values that are obtained
  3589. /// by invoking a transform function on each element of the input sequence.
  3590. /// </summary>
  3591. /// <typeparam name="TSource">The type of elements of <paramref name="source"/>.</typeparam>
  3592. /// <param name="source">A sequence of values that are used to calculate an average.</param>
  3593. /// <param name="selector">A transform function to apply to each element.</param>
  3594. /// <returns>The average of the sequence of values.</returns>
  3595. /// <exception cref="T:System.ArgumentNullException">
  3596. /// <paramref name="source"/> or <paramref name="selector"/> is a null reference (Nothing in Visual Basic).
  3597. /// </exception>
  3598. /// <exception cref="T:System.InvalidOperationException">
  3599. /// <paramref name="source"/> contains no elements.
  3600. /// </exception>
  3601. /// <exception cref="T:System.AggregateException">
  3602. /// One or more exceptions occurred during the evaluation of the query.
  3603. /// </exception>
  3604. /// <exception cref="T:System.OperationCanceledException">
  3605. /// The query was canceled.
  3606. /// </exception>
  3607. public static float Average<TSource>(this ParallelQuery<TSource> source, Func<TSource, float> selector)
  3608. {
  3609. return source.Select(selector).Average();
  3610. }
  3611. /// <summary>
  3612. /// Computes in parallel the average of a sequence of values that are obtained
  3613. /// by invoking a transform function on each element of the input sequence.
  3614. /// </summary>
  3615. /// <typeparam name="TSource">The type of elements of <paramref name="source"/>.</typeparam>
  3616. /// <param name="source">A sequence of values that are used to calculate an average.</param>
  3617. /// <param name="selector">A transform function to apply to each element.</param>
  3618. /// <returns>The average of the sequence of values.</returns>
  3619. /// <exception cref="T:System.ArgumentNullException">
  3620. /// <paramref name="source"/> or <paramref name="selector"/> is a null reference (Nothing in Visual Basic).
  3621. /// </exception>
  3622. /// <exception cref="T:System.AggregateException">
  3623. /// One or more exceptions occurred during the evaluation of the query.
  3624. /// </exception>
  3625. /// <exception cref="T:System.OperationCanceledException">
  3626. /// The query was canceled.
  3627. /// </exception>
  3628. public static float? Average<TSource>(this ParallelQuery<TSource> source, Func<TSource, float?> selector)
  3629. {
  3630. return source.Select(selector).Average();
  3631. }
  3632. /// <summary>
  3633. /// Computes in parallel the average of a sequence of values that are obtained
  3634. /// by invoking a transform function on each element of the input sequence.
  3635. /// </summary>
  3636. /// <typeparam name="TSource">The type of elements of <paramref name="source"/>.</typeparam>
  3637. /// <param name="source">A sequence of values that are used to calculate an average.</param>
  3638. /// <param name="selector">A transform function to apply to each element.</param>
  3639. /// <returns>The average of the sequence of values.</returns>
  3640. /// <exception cref="T:System.ArgumentNullException">
  3641. /// <paramref name="source"/> or <paramref name="selector"/> is a null reference (Nothing in Visual Basic).
  3642. /// </exception>
  3643. /// <exception cref="T:System.InvalidOperationException">
  3644. /// <paramref name="source"/> contains no elements.
  3645. /// </exception>
  3646. /// <exception cref="T:System.AggregateException">
  3647. /// One or more exceptions occurred during the evaluation of the query.
  3648. /// </exception>
  3649. /// <exception cref="T:System.OperationCanceledException">
  3650. /// The query was canceled.
  3651. /// </exception>
  3652. public static double Average<TSource>(this ParallelQuery<TSource> source, Func<TSource, double> selector)
  3653. {
  3654. return source.Select(selector).Average();
  3655. }
  3656. /// <summary>
  3657. /// Computes in parallel the average of a sequence of values that are obtained
  3658. /// by invoking a transform function on each element of the input sequence.
  3659. /// </summary>
  3660. /// <typeparam name="TSource">The type of elements of <paramref name="source"/>.</typeparam>
  3661. /// <param name="source">A sequence of values that are used to calculate an average.</param>
  3662. /// <param name="selector">A transform function to apply to each element.</param>
  3663. /// <returns>The average of the sequence of values.</returns>
  3664. /// <exception cref="T:System.ArgumentNullException">
  3665. /// <paramref name="source"/> or <paramref name="selector"/> is a null reference (Nothing in Visual Basic).
  3666. /// </exception>
  3667. /// <exception cref="T:System.AggregateException">
  3668. /// One or more exceptions occurred during the evaluation of the query.
  3669. /// </exception>
  3670. /// <exception cref="T:System.OperationCanceledException">
  3671. /// The query was canceled.
  3672. /// </exception>
  3673. public static double? Average<TSource>(this ParallelQuery<TSource> source, Func<TSource, double?> selector)
  3674. {
  3675. return source.Select(selector).Average();
  3676. }
  3677. /// <summary>
  3678. /// Computes in parallel the average of a sequence of values that are obtained
  3679. /// by invoking a transform function on each element of the input sequence.
  3680. /// </summary>
  3681. /// <typeparam name="TSource">The type of elements of <paramref name="source"/>.</typeparam>
  3682. /// <param name="source">A sequence of values that are used to calculate an average.</param>
  3683. /// <param name="selector">A transform function to apply to each element.</param>
  3684. /// <returns>The average of the sequence of values.</returns>
  3685. /// <exception cref="T:System.ArgumentNullException">
  3686. /// <paramref name="source"/> or <paramref name="selector"/> is a null reference (Nothing in Visual Basic).
  3687. /// </exception>
  3688. /// <exception cref="T:System.InvalidOperationException">
  3689. /// <paramref name="source"/> contains no elements.
  3690. /// </exception>
  3691. /// <exception cref="T:System.AggregateException">
  3692. /// One or more exceptions occurred during the evaluation of the query.
  3693. /// </exception>
  3694. /// <exception cref="T:System.OperationCanceledException">
  3695. /// The query was canceled.
  3696. /// </exception>
  3697. public static decimal Average<TSource>(this ParallelQuery<TSource> source, Func<TSource, decimal> selector)
  3698. {
  3699. return source.Select(selector).Average();
  3700. }
  3701. /// <summary>
  3702. /// Computes in parallel the average of a sequence of values that are obtained
  3703. /// by invoking a transform function on each element of the input sequence.
  3704. /// </summary>
  3705. /// <typeparam name="TSource">The type of elements of <paramref name="source"/>.</typeparam>
  3706. /// <param name="source">A sequence of values that are used to calculate an average.</param>
  3707. /// <param name="selector">A transform function to apply to each element.</param>
  3708. /// <returns>The average of the sequence of values.</returns>
  3709. /// <exception cref="T:System.ArgumentNullException">
  3710. /// <paramref name="source"/> or <paramref name="selector"/> is a null reference (Nothing in Visual Basic).
  3711. /// </exception>
  3712. /// <exception cref="T:System.AggregateException">
  3713. /// One or more exceptions occurred during the evaluation of the query.
  3714. /// </exception>
  3715. /// <exception cref="T:System.OperationCanceledException">
  3716. /// The query was canceled.
  3717. /// </exception>
  3718. public static decimal? Average<TSource>(this ParallelQuery<TSource> source, Func<TSource, decimal?> selector)
  3719. {
  3720. return source.Select(selector).Average();
  3721. }
  3722. //-----------------------------------------------------------------------------------
  3723. // Any returns true if there exists an element for which the predicate returns true.
  3724. //
  3725. /// <summary>
  3726. /// Determines in parallel whether any element of a sequence satisfies a condition.
  3727. /// </summary>
  3728. /// <typeparam name="TSource">The type of elements of <paramref name="source"/>.</typeparam>
  3729. /// <param name="source">An IEnumerable whose elements to apply the predicate to.</param>
  3730. /// <param name="predicate">A function to test each element for a condition.</param>
  3731. /// <returns>
  3732. /// true if any elements in the source sequence pass the test in the specified predicate; otherwise, false.
  3733. /// </returns>
  3734. /// <exception cref="T:System.ArgumentNullException">
  3735. /// <paramref name="source"/> or <paramref name="predicate"/> is a null reference (Nothing in Visual Basic).
  3736. /// </exception>
  3737. /// <exception cref="T:System.AggregateException">
  3738. /// One or more exceptions occurred during the evaluation of the query.
  3739. /// </exception>
  3740. /// <exception cref="T:System.OperationCanceledException">
  3741. /// The query was canceled.
  3742. /// </exception>
  3743. public static bool Any<TSource>(this ParallelQuery<TSource> source, Func<TSource, bool> predicate)
  3744. {
  3745. if (source == null) throw new ArgumentNullException("source");
  3746. if (predicate == null) throw new ArgumentNullException("predicate");
  3747. return new AnyAllSearchOperator<TSource>(source, true, predicate).Aggregate();
  3748. }
  3749. /// <summary>
  3750. /// Determines whether a parallel sequence contains any elements.
  3751. /// </summary>
  3752. /// <typeparam name="TSource">The type of elements of <paramref name="source"/>.</typeparam>
  3753. /// <param name="source">The IEnumerable to check for emptiness.</param>
  3754. /// <returns>true if the source sequence contains any elements; otherwise, false.</returns>
  3755. /// <exception cref="T:System.ArgumentNullException">
  3756. /// <paramref name="source"/> is a null reference (Nothing in Visual Basic).
  3757. /// </exception>
  3758. /// <exception cref="T:System.AggregateException">
  3759. /// One or more exceptions occurred during the evaluation of the query.
  3760. /// </exception>
  3761. /// <exception cref="T:System.OperationCanceledException">
  3762. /// The query was canceled.
  3763. /// </exception>
  3764. public static bool Any<TSource>(this ParallelQuery<TSource> source)
  3765. {
  3766. if (source == null) throw new ArgumentNullException("source");
  3767. return Any(source, x => true);
  3768. }
  3769. //-----------------------------------------------------------------------------------
  3770. // All returns false if there exists an element for which the predicate returns false.
  3771. //
  3772. /// <summary>
  3773. /// Determines in parallel whether all elements of a sequence satisfy a condition.
  3774. /// </summary>
  3775. /// <typeparam name="TSource">The type of elements of <paramref name="source"/>.</typeparam>
  3776. /// <param name="source">A sequence whose elements to apply the predicate to.</param>
  3777. /// <param name="predicate">A function to test each element for a condition.</param>
  3778. /// <returns>
  3779. /// true if all elements in the source sequence pass the test in the specified predicate; otherwise, false.
  3780. /// </returns>
  3781. /// <exception cref="T:System.ArgumentNullException">
  3782. /// <paramref name="source"/> or <paramref name="predicate"/> is a null reference (Nothing in Visual Basic).
  3783. /// </exception>
  3784. /// <exception cref="T:System.AggregateException">
  3785. /// One or more exceptions occurred during the evaluation of the query.
  3786. /// </exception>
  3787. /// <exception cref="T:System.OperationCanceledException">
  3788. /// The query was canceled.
  3789. /// </exception>
  3790. public static bool All<TSource>(this ParallelQuery<TSource> source, Func<TSource, bool> predicate)
  3791. {
  3792. if (source == null) throw new ArgumentNullException("source");
  3793. if (predicate == null) throw new ArgumentNullException("predicate");
  3794. return new AnyAllSearchOperator<TSource>(source, false, predicate).Aggregate();
  3795. }
  3796. //-----------------------------------------------------------------------------------
  3797. // Contains returns true if the specified value was found in the data source.
  3798. //
  3799. /// <summary>
  3800. /// Determines in parallel whether a sequence contains a specified element
  3801. /// by using the default equality comparer.
  3802. /// </summary>
  3803. /// <typeparam name="TSource">The type of elements of <paramref name="source"/>.</typeparam>
  3804. /// <param name="source">A sequence in which to locate a value.</param>
  3805. /// <param name="value">The value to locate in the sequence.</param>
  3806. /// <returns>
  3807. /// true if the source sequence contains an element that has the specified value; otherwise, false.
  3808. /// </returns>
  3809. /// <exception cref="T:System.ArgumentNullException">
  3810. /// <paramref name="source"/> is a null reference (Nothing in Visual Basic).
  3811. /// </exception>
  3812. /// <exception cref="T:System.AggregateException">
  3813. /// One or more exceptions occurred during the evaluation of the query.
  3814. /// </exception>
  3815. /// <exception cref="T:System.OperationCanceledException">
  3816. /// The query was canceled.
  3817. /// </exception>
  3818. public static bool Contains<TSource>(this ParallelQuery<TSource> source, TSource value)
  3819. {
  3820. return Contains(source, value, null);
  3821. }
  3822. /// <summary>
  3823. /// Determines in parallel whether a sequence contains a specified element by using a
  3824. /// specified IEqualityComparer{T}.
  3825. /// </summary>
  3826. /// <typeparam name="TSource">The type of elements of <paramref name="source"/>.</typeparam>
  3827. /// <param name="source">A sequence in which to locate a value.</param>
  3828. /// <param name="value">The value to locate in the sequence.</param>
  3829. /// <param name="comparer">An equality comparer to compare values.</param>
  3830. /// <returns>
  3831. /// true if the source sequence contains an element that has the specified value; otherwise, false.
  3832. /// </returns>
  3833. /// <exception cref="T:System.ArgumentNullException">
  3834. /// <paramref name="source"/> is a null reference (Nothing in Visual Basic).
  3835. /// </exception>
  3836. /// <exception cref="T:System.AggregateException">
  3837. /// One or more exceptions occurred during the evaluation of the query.
  3838. /// </exception>
  3839. /// <exception cref="T:System.OperationCanceledException">
  3840. /// The query was canceled.
  3841. /// </exception>
  3842. public static bool Contains<TSource>(this ParallelQuery<TSource> source, TSource value, IEqualityComparer<TSource> comparer)
  3843. {
  3844. if (source == null) throw new ArgumentNullException("source");
  3845. // @PERF: there are many simple optimizations we can make for collection types with known sizes.
  3846. return new ContainsSearchOperator<TSource>(source, value, comparer).Aggregate();
  3847. }
  3848. /*===================================================================================
  3849. * TOP (TAKE, SKIP) OPERATORS
  3850. *===================================================================================*/
  3851. //-----------------------------------------------------------------------------------
  3852. // Take will take the first [0..count) contiguous elements from the input.
  3853. //
  3854. /// <summary>
  3855. /// Returns a specified number of contiguous elements from the start of a parallel sequence.
  3856. /// </summary>
  3857. /// <typeparam name="TSource">The type of elements of <paramref name="source"/>.</typeparam>
  3858. /// <param name="source">The sequence to return elements from.</param>
  3859. /// <param name="count">The number of elements to return.</param>
  3860. /// <returns>
  3861. /// A sequence that contains the specified number of elements from the start of the input sequence.
  3862. /// </returns>
  3863. /// <exception cref="T:System.ArgumentNullException">
  3864. /// <paramref name="source"/> is a null reference (Nothing in Visual Basic).
  3865. /// </exception>
  3866. public static ParallelQuery<TSource> Take<TSource>(this ParallelQuery<TSource> source, int count)
  3867. {
  3868. if (source == null) throw new ArgumentNullException("source");
  3869. if (count > 0)
  3870. {
  3871. return new TakeOrSkipQueryOperator<TSource>(source, count, true);
  3872. }
  3873. else
  3874. {
  3875. return ParallelEnumerable.Empty<TSource>();
  3876. }
  3877. }
  3878. //-----------------------------------------------------------------------------------
  3879. // TakeWhile will take the first [0..N) contiguous elements, where N is the smallest
  3880. // index of an element for which the predicate yields false.
  3881. //
  3882. /// <summary>
  3883. /// Returns elements from a parallel sequence as long as a specified condition is true.
  3884. /// </summary>
  3885. /// <typeparam name="TSource">The type of elements of <paramref name="source"/>.</typeparam>
  3886. /// <param name="source">The sequence to return elements from.</param>
  3887. /// <param name="predicate">A function to test each element for a condition.</param>
  3888. /// <returns>
  3889. /// A sequence that contains the elements from the input sequence that occur before
  3890. /// the element at which the test no longer passes.
  3891. /// </returns>
  3892. /// <exception cref="T:System.ArgumentNullException">
  3893. /// <paramref name="source"/> or <paramref name="predicate"/> is a null reference (Nothing in Visual Basic).
  3894. /// </exception>
  3895. public static ParallelQuery<TSource> TakeWhile<TSource>(this ParallelQuery<TSource> source, Func<TSource, bool> predicate)
  3896. {
  3897. if (source == null) throw new ArgumentNullException("source");
  3898. if (predicate == null) throw new ArgumentNullException("predicate");
  3899. return new TakeOrSkipWhileQueryOperator<TSource>(source, predicate, null, true);
  3900. }
  3901. /// <summary>
  3902. /// Returns elements from a parallel sequence as long as a specified condition is true.
  3903. /// The element's index is used in the logic of the predicate function.
  3904. /// </summary>
  3905. /// <typeparam name="TSource">The type of elements of <paramref name="source"/>.</typeparam>
  3906. /// <param name="source">The sequence to return elements from.</param>
  3907. /// <param name="predicate">
  3908. /// A function to test each source element for a condition; the second parameter of the
  3909. /// function represents the index of the source element.
  3910. /// </param>
  3911. /// <returns>
  3912. /// A sequence that contains elements from the input sequence that occur before
  3913. /// the element at which the test no longer passes.
  3914. /// </returns>
  3915. /// <exception cref="T:System.ArgumentNullException">
  3916. /// <paramref name="source"/> or <paramref name="predicate"/> is a null reference (Nothing in Visual Basic).
  3917. /// </exception>
  3918. public static ParallelQuery<TSource> TakeWhile<TSource>(this ParallelQuery<TSource> source, Func<TSource, int, bool> predicate)
  3919. {
  3920. if (source == null) throw new ArgumentNullException("source");
  3921. if (predicate == null) throw new ArgumentNullException("predicate");
  3922. return new TakeOrSkipWhileQueryOperator<TSource>(source, null, predicate, true);
  3923. }
  3924. //-----------------------------------------------------------------------------------
  3925. // Skip will take the last [count..M) contiguous elements from the input, where M is
  3926. // the size of the input.
  3927. //
  3928. /// <summary>
  3929. /// Bypasses a specified number of elements in a parallel sequence and then returns the remaining elements.
  3930. /// </summary>
  3931. /// <typeparam name="TSource">The type of elements of <paramref name="source"/>.</typeparam>
  3932. /// <param name="source">The sequence to return elements from.</param>
  3933. /// <param name="count">The number of elements to skip before returning the remaining elements.</param>
  3934. /// <returns>
  3935. /// A sequence that contains the elements that occur after the specified index in the input sequence.
  3936. /// </returns>
  3937. /// <exception cref="T:System.ArgumentNullException">
  3938. /// <paramref name="source"/> is a null reference (Nothing in Visual Basic).
  3939. /// </exception>
  3940. public static ParallelQuery<TSource> Skip<TSource>(this ParallelQuery<TSource> source, int count)
  3941. {
  3942. if (source == null) throw new ArgumentNullException("source");
  3943. // If the count is 0 (or less) we just return the whole stream.
  3944. if (count <= 0)
  3945. {
  3946. return source;
  3947. }
  3948. return new TakeOrSkipQueryOperator<TSource>(source, count, false);
  3949. }
  3950. //-----------------------------------------------------------------------------------
  3951. // SkipWhile will take the last [N..M) contiguous elements, where N is the smallest
  3952. // index of an element for which the predicate yields false, and M is the size of
  3953. // the input data source.
  3954. //
  3955. /// <summary>
  3956. /// Bypasses elements in a parallel sequence as long as a specified
  3957. /// condition is true and then returns the remaining elements.
  3958. /// </summary>
  3959. /// <typeparam name="TSource">The type of elements of <paramref name="source"/>.</typeparam>
  3960. /// <param name="source">The sequence to return elements from.</param>
  3961. /// <param name="predicate">A function to test each element for a condition.</param>
  3962. /// <returns>A sequence that contains the elements from the input sequence starting at
  3963. /// the first element in the linear series that does not pass the test specified by
  3964. /// <B>predicate</B>.</returns>
  3965. /// <exception cref="T:System.ArgumentNullException">
  3966. /// <paramref name="source"/> or <paramref name="predicate"/> is a null reference (Nothing in Visual Basic).
  3967. /// </exception>
  3968. public static ParallelQuery<TSource> SkipWhile<TSource>(this ParallelQuery<TSource> source, Func<TSource, bool> predicate)
  3969. {
  3970. if (source == null) throw new ArgumentNullException("source");
  3971. if (predicate == null) throw new ArgumentNullException("predicate");
  3972. return new TakeOrSkipWhileQueryOperator<TSource>(source, predicate, null, false);
  3973. }
  3974. /// <summary>
  3975. /// Bypasses elements in a parallel sequence as long as a specified condition is true and
  3976. /// then returns the remaining elements. The element's index is used in the logic of
  3977. /// the predicate function.
  3978. /// </summary>
  3979. /// <typeparam name="TSource">The type of elements of <paramref name="source"/>.</typeparam>
  3980. /// <param name="source">The sequence to return elements from.</param>
  3981. /// <param name="predicate">
  3982. /// A function to test each source element for a condition; the
  3983. /// second parameter of the function represents the index of the source element.
  3984. /// </param>
  3985. /// <returns>
  3986. /// A sequence that contains the elements from the input sequence starting at the
  3987. /// first element in the linear series that does not pass the test specified by
  3988. /// <B>predicate</B>.
  3989. /// </returns>
  3990. /// <exception cref="T:System.ArgumentNullException">
  3991. /// <paramref name="source"/> or <paramref name="predicate"/> is a null reference (Nothing in Visual Basic).
  3992. /// </exception>
  3993. public static ParallelQuery<TSource> SkipWhile<TSource>(this ParallelQuery<TSource> source, Func<TSource, int, bool> predicate)
  3994. {
  3995. if (source == null) throw new ArgumentNullException("source");
  3996. if (predicate == null) throw new ArgumentNullException("predicate");
  3997. return new TakeOrSkipWhileQueryOperator<TSource>(source, null, predicate, false);
  3998. }
  3999. /*===================================================================================
  4000. * SET OPERATORS
  4001. *===================================================================================*/
  4002. //-----------------------------------------------------------------------------------
  4003. // Appends the second data source to the first, preserving order in the process.
  4004. //
  4005. /// <summary>
  4006. /// Concatenates two parallel sequences.
  4007. /// </summary>
  4008. /// <typeparam name="TSource">The type of the elements of the input sequences.</typeparam>
  4009. /// <param name="first">The first sequence to concatenate.</param>
  4010. /// <param name="second">The sequence to concatenate to the first sequence.</param>
  4011. /// <returns>A sequence that contains the concatenated elements of the two input sequences.</returns>
  4012. /// <exception cref="T:System.ArgumentNullException">
  4013. /// <paramref name="first"/> or <paramref name="second"/> is a null reference (Nothing in Visual Basic).
  4014. /// </exception>
  4015. public static ParallelQuery<TSource> Concat<TSource>(this ParallelQuery<TSource> first, ParallelQuery<TSource> second)
  4016. {
  4017. if (first == null) throw new ArgumentNullException("first");
  4018. if (second == null) throw new ArgumentNullException("second");
  4019. return new ConcatQueryOperator<TSource>(first, second);
  4020. }
  4021. /// <summary>
  4022. /// This Concat overload should never be called.
  4023. /// This method is marked as obsolete and always throws <see cref="System.NotSupportedException"/> when called.
  4024. /// </summary>
  4025. /// <typeparam name="TSource">This type parameter is not used.</typeparam>
  4026. /// <param name="first">This parameter is not used.</param>
  4027. /// <param name="second">This parameter is not used.</param>
  4028. /// <returns>This overload always throws a <see cref="System.NotSupportedException"/>.</returns>
  4029. /// <exception cref="T:System.NotSupportedException">The exception that occurs when this method is called.</exception>
  4030. /// <remarks>
  4031. /// This overload exists to disallow usage of Concat with a left data source of type
  4032. /// <see cref="System.Linq.ParallelQuery{TSource}"/> and a right data source of type <see cref="System.Collections.Generic.IEnumerable{TSource}"/>.
  4033. /// Otherwise, the Concat operator would appear to be binding to the parallel implementation,
  4034. /// but would in reality bind to the sequential implementation.
  4035. /// </remarks>
  4036. [Obsolete(RIGHT_SOURCE_NOT_PARALLEL_STR)]
  4037. public static ParallelQuery<TSource> Concat<TSource>(this ParallelQuery<TSource> first, IEnumerable<TSource> second)
  4038. {
  4039. throw new NotSupportedException(SR.GetString(SR.ParallelEnumerable_BinaryOpMustUseAsParallel));
  4040. }
  4041. //-----------------------------------------------------------------------------------
  4042. // Compares two input streams pairwise for equality.
  4043. //
  4044. /// <summary>
  4045. /// Determines whether two parallel sequences are equal by comparing the elements by using
  4046. /// the default equality comparer for their type.
  4047. /// </summary>
  4048. /// <typeparam name="TSource">The type of the elements of the input sequences.</typeparam>
  4049. /// <param name="first">A sequence to compare to <b>second</b>.</param>
  4050. /// <param name="second">A sequence to compare to the first input sequence.</param>
  4051. /// <returns>
  4052. /// true if the two source sequences are of equal length and their corresponding elements
  4053. /// are equal according to the default equality comparer for their type; otherwise, false.
  4054. /// </returns>
  4055. /// <exception cref="T:System.ArgumentNullException">
  4056. /// <paramref name="first"/> or <paramref name="second"/> is a null reference (Nothing in Visual Basic).
  4057. /// </exception>
  4058. /// <exception cref="T:System.AggregateException">
  4059. /// One or more exceptions occurred during the evaluation of the query.
  4060. /// </exception>
  4061. /// <exception cref="T:System.OperationCanceledException">
  4062. /// The query was canceled.
  4063. /// </exception>
  4064. public static bool SequenceEqual<TSource>(this ParallelQuery<TSource> first, ParallelQuery<TSource> second)
  4065. {
  4066. if (first == null) throw new ArgumentNullException("first");
  4067. if (second == null) throw new ArgumentNullException("second");
  4068. return SequenceEqual<TSource>(first, second, null);
  4069. }
  4070. /// <summary>
  4071. /// This SequenceEqual overload should never be called.
  4072. /// This method is marked as obsolete and always throws <see cref="System.NotSupportedException"/> when called.
  4073. /// </summary>
  4074. /// <typeparam name="TSource">This type parameter is not used.</typeparam>
  4075. /// <param name="first">This parameter is not used.</param>
  4076. /// <param name="second">This parameter is not used.</param>
  4077. /// <returns>This overload always throws a <see cref="System.NotSupportedException"/>.</returns>
  4078. /// <exception cref="T:System.NotSupportedException">Thrown every time this method is called.</exception>
  4079. /// <remarks>
  4080. /// This overload exists to disallow usage of SequenceEqual with a left data source of type
  4081. /// <see cref="System.Linq.ParallelQuery{TSource}"/> and a right data source of type <see cref="System.Collections.Generic.IEnumerable{TSource}"/>.
  4082. /// Otherwise, the SequenceEqual operator would appear to be binding to the parallel implementation,
  4083. /// but would in reality bind to the sequential implementation.
  4084. /// </remarks>
  4085. [Obsolete(RIGHT_SOURCE_NOT_PARALLEL_STR)]
  4086. public static bool SequenceEqual<TSource>(this ParallelQuery<TSource> first, IEnumerable<TSource> second)
  4087. {
  4088. throw new NotSupportedException(SR.GetString(SR.ParallelEnumerable_BinaryOpMustUseAsParallel));
  4089. }
  4090. /// <summary>
  4091. /// Determines whether two parallel sequences are equal by comparing their elements by
  4092. /// using a specified IEqualityComparer{T}.
  4093. /// </summary>
  4094. /// <typeparam name="TSource">The type of the elements of the input sequences.</typeparam>
  4095. /// <param name="first">A sequence to compare to <paramref name="second"/>.</param>
  4096. /// <param name="second">A sequence to compare to the first input sequence.</param>
  4097. /// <param name="comparer">An IEqualityComparer&lt;(Of &lt;(T&gt;)&gt;) to use to compare elements.</param>
  4098. /// <returns>
  4099. /// true if the two source sequences are of equal length and their corresponding
  4100. /// elements are equal according to the default equality comparer for their type; otherwise, false.
  4101. /// </returns>
  4102. /// <exception cref="T:System.ArgumentNullException">
  4103. /// <paramref name="first"/> or <paramref name="second"/> is a null reference (Nothing in Visual Basic).
  4104. /// </exception>
  4105. /// <exception cref="T:System.AggregateException">
  4106. /// One or more exceptions occurred during the evaluation of the query.
  4107. /// </exception>
  4108. /// <exception cref="T:System.OperationCanceledException">
  4109. /// The query was canceled.
  4110. /// </exception>
  4111. public static bool SequenceEqual<TSource>(this ParallelQuery<TSource> first, ParallelQuery<TSource> second, IEqualityComparer<TSource> comparer)
  4112. {
  4113. if (first == null) throw new ArgumentNullException("first");
  4114. if (second == null) throw new ArgumentNullException("second");
  4115. // If comparer is null, use the default one
  4116. comparer = comparer ?? EqualityComparer<TSource>.Default;
  4117. QueryOperator<TSource> leftOp = QueryOperator<TSource>.AsQueryOperator(first);
  4118. QueryOperator<TSource> rightOp = QueryOperator<TSource>.AsQueryOperator(second);
  4119. // We use a fully-qualified type name for Shared here to prevent the conflict between System.Linq.Parallel.Shared<>
  4120. // and System.Threading.Shared<> in the 3.5 legacy build.
  4121. QuerySettings settings = leftOp.SpecifiedQuerySettings.Merge(rightOp.SpecifiedQuerySettings)
  4122. .WithDefaults()
  4123. .WithPerExecutionSettings(new CancellationTokenSource(), new System.Linq.Parallel.Shared<bool>(false));
  4124. // If first.GetEnumerator throws an exception, we don't want to wrap it with an AggregateException.
  4125. IEnumerator<TSource> e1 = first.GetEnumerator();
  4126. try
  4127. {
  4128. // If second.GetEnumerator throws an exception, we don't want to wrap it with an AggregateException.
  4129. IEnumerator<TSource> e2 = second.GetEnumerator();
  4130. try
  4131. {
  4132. while (e1.MoveNext())
  4133. {
  4134. if (!(e2.MoveNext() && comparer.Equals(e1.Current, e2.Current))) return false;
  4135. }
  4136. if (e2.MoveNext()) return false;
  4137. }
  4138. catch (ThreadAbortException)
  4139. {
  4140. // Do not wrap ThreadAbortExceptions
  4141. throw;
  4142. }
  4143. catch (Exception ex)
  4144. {
  4145. ExceptionAggregator.ThrowOCEorAggregateException(ex, settings.CancellationState);
  4146. }
  4147. finally
  4148. {
  4149. DisposeEnumerator<TSource>(e2, settings.CancellationState);
  4150. }
  4151. }
  4152. finally
  4153. {
  4154. DisposeEnumerator<TSource>(e1, settings.CancellationState);
  4155. }
  4156. return true;
  4157. }
  4158. /// <summary>
  4159. /// A helper method for SequenceEqual to dispose an enumerator. If an exception is thrown by the disposal,
  4160. /// it gets wrapped into an AggregateException, unless it is an OCE with the query's CancellationToken.
  4161. /// </summary>
  4162. private static void DisposeEnumerator<TSource>(IEnumerator<TSource> e, CancellationState cancelState)
  4163. {
  4164. try
  4165. {
  4166. e.Dispose();
  4167. }
  4168. catch (ThreadAbortException)
  4169. {
  4170. // Do not wrap ThreadAbortExceptions
  4171. throw;
  4172. }
  4173. catch (Exception ex)
  4174. {
  4175. ExceptionAggregator.ThrowOCEorAggregateException(ex, cancelState);
  4176. }
  4177. }
  4178. /// <summary>
  4179. /// This SequenceEqual overload should never be called.
  4180. /// This method is marked as obsolete and always throws <see cref="System.NotSupportedException"/> when called.
  4181. /// </summary>
  4182. /// <typeparam name="TSource">This type parameter is not used.</typeparam>
  4183. /// <param name="first">This parameter is not used.</param>
  4184. /// <param name="second">This parameter is not used.</param>
  4185. /// <param name="comparer">This parameter is not used.</param>
  4186. /// <returns>This overload always throws a <see cref="System.NotSupportedException"/>.</returns>
  4187. /// <exception cref="T:System.NotSupportedException">Thrown every time this method is called.</exception>
  4188. /// <remarks>
  4189. /// This overload exists to disallow usage of SequenceEqual with a left data source of type
  4190. /// <see cref="System.Linq.ParallelQuery{TSource}"/> and a right data source of type <see cref="System.Collections.Generic.IEnumerable{TSource}"/>.
  4191. /// Otherwise, the SequenceEqual operator would appear to be binding to the parallel implementation,
  4192. /// but would in reality bind to sequential implementation.
  4193. /// </remarks>
  4194. [Obsolete(RIGHT_SOURCE_NOT_PARALLEL_STR)]
  4195. public static bool SequenceEqual<TSource>(this ParallelQuery<TSource> first, IEnumerable<TSource> second, IEqualityComparer<TSource> comparer)
  4196. {
  4197. throw new NotSupportedException(SR.GetString(SR.ParallelEnumerable_BinaryOpMustUseAsParallel));
  4198. }
  4199. //-----------------------------------------------------------------------------------
  4200. // Calculates the distinct set of elements in the single input data source.
  4201. //
  4202. /// <summary>
  4203. /// Returns distinct elements from a parallel sequence by using the
  4204. /// default equality comparer to compare values.
  4205. /// </summary>
  4206. /// <typeparam name="TSource">The type of the elements of <paramref name="source"/>.</typeparam>
  4207. /// <param name="source">The sequence to remove duplicate elements from.</param>
  4208. /// <returns>A sequence that contains distinct elements from the source sequence.</returns>
  4209. /// <exception cref="T:System.ArgumentNullException">
  4210. /// <paramref name="source"/> is a null reference (Nothing in Visual Basic).
  4211. /// </exception>
  4212. public static ParallelQuery<TSource> Distinct<TSource>(
  4213. this ParallelQuery<TSource> source)
  4214. {
  4215. return Distinct(source, null);
  4216. }
  4217. /// <summary>
  4218. /// Returns distinct elements from a parallel sequence by using a specified
  4219. /// IEqualityComparer{T} to compare values.
  4220. /// </summary>
  4221. /// <typeparam name="TSource">The type of the elements of <paramref name="source"/>.</typeparam>
  4222. /// <param name="source">The sequence to remove duplicate elements from.</param>
  4223. /// <param name="comparer">An IEqualityComparer&lt;(Of &lt;(T&gt;)&gt;) to compare values.</param>
  4224. /// <returns>A sequence that contains distinct elements from the source sequence.</returns>
  4225. /// <exception cref="T:System.ArgumentNullException">
  4226. /// <paramref name="source"/> is a null reference (Nothing in Visual Basic).
  4227. /// </exception>
  4228. public static ParallelQuery<TSource> Distinct<TSource>(
  4229. this ParallelQuery<TSource> source, IEqualityComparer<TSource> comparer)
  4230. {
  4231. if (source == null) throw new ArgumentNullException("source");
  4232. return new DistinctQueryOperator<TSource>(source, comparer);
  4233. }
  4234. //-----------------------------------------------------------------------------------
  4235. // Calculates the union between the first and second data sources.
  4236. //
  4237. /// <summary>
  4238. /// Produces the set union of two parallel sequences by using the default equality comparer.
  4239. /// </summary>
  4240. /// <typeparam name="TSource">The type of the elements of the input sequences.</typeparam>
  4241. /// <param name="first">A sequence whose distinct elements form the first set for the union.</param>
  4242. /// <param name="second">A sequence whose distinct elements form the second set for the union.</param>
  4243. /// <returns>A sequence that contains the elements from both input sequences, excluding duplicates.</returns>
  4244. /// <exception cref="T:System.ArgumentNullException">
  4245. /// <paramref name="first"/> or <paramref name="second"/> is a null reference (Nothing in Visual Basic).
  4246. /// </exception>
  4247. public static ParallelQuery<TSource> Union<TSource>(
  4248. this ParallelQuery<TSource> first, ParallelQuery<TSource> second)
  4249. {
  4250. return Union(first, second, null);
  4251. }
  4252. /// <summary>
  4253. /// This Union overload should never be called.
  4254. /// This method is marked as obsolete and always throws <see cref="System.NotSupportedException"/> when called.
  4255. /// </summary>
  4256. /// <typeparam name="TSource">This type parameter is not used.</typeparam>
  4257. /// <param name="first">This parameter is not used.</param>
  4258. /// <param name="second">This parameter is not used.</param>
  4259. /// <returns>This overload always throws a <see cref="System.NotSupportedException"/>.</returns>
  4260. /// <exception cref="T:System.NotSupportedException">The exception that occurs when this method is called.</exception>
  4261. /// <remarks>
  4262. /// This overload exists to disallow usage of Union with a left data source of type
  4263. /// <see cref="System.Linq.ParallelQuery{TSource}"/> and a right data source of type <see cref="System.Collections.Generic.IEnumerable{TSource}"/>.
  4264. /// Otherwise, the Union operator would appear to be binding to the parallel implementation,
  4265. /// but would in reality bind to sequential implementation.
  4266. /// </remarks>
  4267. [Obsolete(RIGHT_SOURCE_NOT_PARALLEL_STR)]
  4268. public static ParallelQuery<TSource> Union<TSource>(
  4269. this ParallelQuery<TSource> first, IEnumerable<TSource> second)
  4270. {
  4271. throw new NotSupportedException(SR.GetString(SR.ParallelEnumerable_BinaryOpMustUseAsParallel));
  4272. }
  4273. /// <summary>
  4274. /// Produces the set union of two parallel sequences by using a specified IEqualityComparer{T}.
  4275. /// </summary>
  4276. /// <typeparam name="TSource">The type of the elements of the input sequences.</typeparam>
  4277. /// <param name="first">A sequence whose distinct elements form the first set for the union.</param>
  4278. /// <param name="second">A sequence whose distinct elements form the second set for the union.</param>
  4279. /// <param name="comparer">An IEqualityComparer&lt;(Of &lt;(T&gt;)&gt;) to compare values.</param>
  4280. /// <returns>A sequence that contains the elements from both input sequences, excluding duplicates.</returns>
  4281. /// <exception cref="T:System.ArgumentNullException">
  4282. /// <paramref name="first"/> or <paramref name="second"/> is a null reference (Nothing in Visual Basic).
  4283. /// </exception>
  4284. public static ParallelQuery<TSource> Union<TSource>(
  4285. this ParallelQuery<TSource> first, ParallelQuery<TSource> second, IEqualityComparer<TSource> comparer)
  4286. {
  4287. if (first == null) throw new ArgumentNullException("first");
  4288. if (second == null) throw new ArgumentNullException("second");
  4289. return new UnionQueryOperator<TSource>(first, second, comparer);
  4290. }
  4291. /// <summary>
  4292. /// This Union overload should never be called.
  4293. /// This method is marked as obsolete and always throws <see cref="System.NotSupportedException"/> when called.
  4294. /// </summary>
  4295. /// <typeparam name="TSource">This type parameter is not used.</typeparam>
  4296. /// <param name="first">This parameter is not used.</param>
  4297. /// <param name="second">This parameter is not used.</param>
  4298. /// <param name="comparer">This parameter is not used.</param>
  4299. /// <returns>This overload always throws a <see cref="System.NotSupportedException"/>.</returns>
  4300. /// <exception cref="T:System.NotSupportedException">The exception that occurs when this method is called.</exception>
  4301. /// <remarks>
  4302. /// This overload exists to disallow usage of Union with a left data source of type
  4303. /// <see cref="System.Linq.ParallelQuery{TSource}"/> and a right data source of type <see cref="System.Collections.Generic.IEnumerable{TSource}"/>.
  4304. /// Otherwise, the Union operator would appear to be binding to the parallel implementation,
  4305. /// but would in reality bind to the sequential implementation.
  4306. /// </remarks>
  4307. [Obsolete(RIGHT_SOURCE_NOT_PARALLEL_STR)]
  4308. public static ParallelQuery<TSource> Union<TSource>(
  4309. this ParallelQuery<TSource> first, IEnumerable<TSource> second, IEqualityComparer<TSource> comparer)
  4310. {
  4311. throw new NotSupportedException(SR.GetString(SR.ParallelEnumerable_BinaryOpMustUseAsParallel));
  4312. }
  4313. //-----------------------------------------------------------------------------------
  4314. // Calculates the intersection between the first and second data sources.
  4315. //
  4316. /// <summary>
  4317. /// Produces the set intersection of two parallel sequences by using the
  4318. /// default equality comparer to compare values.
  4319. /// </summary>
  4320. /// <typeparam name="TSource">The type of the elements of the input sequences.</typeparam>
  4321. /// <param name="first"
  4322. /// >A sequence whose distinct elements that also appear in <paramref name="second"/> will be returned.
  4323. /// </param>
  4324. /// <param name="second">
  4325. /// A sequence whose distinct elements that also appear in the first sequence will be returned.
  4326. /// </param>
  4327. /// <returns>A sequence that contains the elements that form the set intersection of two sequences.</returns>
  4328. /// <exception cref="T:System.ArgumentNullException">
  4329. /// <paramref name="first"/> or <paramref name="second"/> is a null reference (Nothing in Visual Basic).
  4330. /// </exception>
  4331. public static ParallelQuery<TSource> Intersect<TSource>(
  4332. this ParallelQuery<TSource> first, ParallelQuery<TSource> second)
  4333. {
  4334. return Intersect(first, second, null);
  4335. }
  4336. /// <summary>
  4337. /// This Intersect overload should never be called.
  4338. /// This method is marked as obsolete and always throws <see cref="System.NotSupportedException"/> when called.
  4339. /// </summary>
  4340. /// <typeparam name="TSource">This type parameter is not used.</typeparam>
  4341. /// <param name="first">This parameter is not used.</param>
  4342. /// <param name="second">This parameter is not used.</param>
  4343. /// <returns>This overload always throws a <see cref="System.NotSupportedException"/>.</returns>
  4344. /// <exception cref="T:System.NotSupportedException">The exception that occurs when this method is called.</exception>
  4345. /// <remarks>
  4346. /// This overload exists to disallow usage of Intersect with a left data source of type
  4347. /// <see cref="System.Linq.ParallelQuery{TSource}"/> and a right data source of type <see cref="System.Collections.Generic.IEnumerable{TSource}"/>.
  4348. /// Otherwise, the Intersect operator would appear to be binding to the parallel implementation,
  4349. /// but would in reality bind to the sequential implementation.
  4350. /// </remarks>
  4351. [Obsolete(RIGHT_SOURCE_NOT_PARALLEL_STR)]
  4352. public static ParallelQuery<TSource> Intersect<TSource>(
  4353. this ParallelQuery<TSource> first, IEnumerable<TSource> second)
  4354. {
  4355. throw new NotSupportedException(SR.GetString(SR.ParallelEnumerable_BinaryOpMustUseAsParallel));
  4356. }
  4357. /// <summary>
  4358. /// Produces the set intersection of two parallel sequences by using
  4359. /// the specified IEqualityComparer{T} to compare values.
  4360. /// </summary>
  4361. /// <typeparam name="TSource">The type of the elements of the input sequences.</typeparam>
  4362. /// <param name="first">
  4363. /// A sequence whose distinct elements that also appear in <paramref name="second"/> will be returned.
  4364. /// </param>
  4365. /// <param name="second">
  4366. /// A sequence whose distinct elements that also appear in the first sequence will be returned.
  4367. /// </param>
  4368. /// <param name="comparer">An IEqualityComparer&lt;(Of &lt;(T&gt;)&gt;) to compare values.</param>
  4369. /// <returns>A sequence that contains the elements that form the set intersection of two sequences.</returns>
  4370. /// <exception cref="T:System.ArgumentNullException">
  4371. /// <paramref name="first"/> or <paramref name="second"/> is a null reference (Nothing in Visual Basic).
  4372. /// </exception>
  4373. public static ParallelQuery<TSource> Intersect<TSource>(
  4374. this ParallelQuery<TSource> first, ParallelQuery<TSource> second, IEqualityComparer<TSource> comparer)
  4375. {
  4376. if (first == null) throw new ArgumentNullException("first");
  4377. if (second == null) throw new ArgumentNullException("second");
  4378. return new IntersectQueryOperator<TSource>(first, second, comparer);
  4379. }
  4380. /// <summary>
  4381. /// This Intersect overload should never be called.
  4382. /// This method is marked as obsolete and always throws <see cref="System.NotSupportedException"/> when called.
  4383. /// </summary>
  4384. /// <typeparam name="TSource">This type parameter is not used.</typeparam>
  4385. /// <param name="first">This parameter is not used.</param>
  4386. /// <param name="second">This parameter is not used.</param>
  4387. /// <param name="comparer">This parameter is not used.</param>
  4388. /// <returns>This overload always throws a <see cref="System.NotSupportedException"/>.</returns>
  4389. /// <exception cref="T:System.NotSupportedException">The exception that occurs when this method is called.</exception>
  4390. /// <remarks>
  4391. /// This overload exists to disallow usage of Intersect with a left data source of type
  4392. /// <see cref="System.Linq.ParallelQuery{TSource}"/> and a right data source of type <see cref="System.Collections.Generic.IEnumerable{TSource}"/>.
  4393. /// Otherwise, the Intersect operator would appear to be binding to the parallel implementation,
  4394. /// but would in reality bind to the sequential implementation.
  4395. /// </remarks>
  4396. [Obsolete(RIGHT_SOURCE_NOT_PARALLEL_STR)]
  4397. public static ParallelQuery<TSource> Intersect<TSource>(
  4398. this ParallelQuery<TSource> first, IEnumerable<TSource> second, IEqualityComparer<TSource> comparer)
  4399. {
  4400. throw new NotSupportedException(SR.GetString(SR.ParallelEnumerable_BinaryOpMustUseAsParallel));
  4401. }
  4402. //-----------------------------------------------------------------------------------
  4403. // Calculates the relative complement of the first and second data sources, that is,
  4404. // the elements in first that are not found in second.
  4405. //
  4406. /// <summary>
  4407. /// Produces the set difference of two parallel sequences by using
  4408. /// the default equality comparer to compare values.
  4409. /// </summary>
  4410. /// <typeparam name="TSource">The type of the elements of the input sequences.</typeparam>
  4411. /// <param name="first">
  4412. /// A sequence whose elements that are not also in <paramref name="second"/> will be returned.
  4413. /// </param>
  4414. /// <param name="second">
  4415. /// A sequence whose elements that also occur in the first sequence will cause those
  4416. /// elements to be removed from the returned sequence.
  4417. /// </param>
  4418. /// <returns>A sequence that contains the set difference of the elements of two sequences.</returns>
  4419. /// <exception cref="T:System.ArgumentNullException">
  4420. /// <paramref name="first"/> or <paramref name="second"/> is a null reference (Nothing in Visual Basic).
  4421. /// </exception>
  4422. public static ParallelQuery<TSource> Except<TSource>(
  4423. this ParallelQuery<TSource> first, ParallelQuery<TSource> second)
  4424. {
  4425. return Except(first, second, null);
  4426. }
  4427. /// <summary>
  4428. /// This Except overload should never be called.
  4429. /// This method is marked as obsolete and always throws <see cref="System.NotSupportedException"/> when called.
  4430. /// </summary>
  4431. /// <typeparam name="TSource">This type parameter is not used.</typeparam>
  4432. /// <param name="first">This parameter is not used.</param>
  4433. /// <param name="second">This parameter is not used.</param>
  4434. /// <returns>This overload always throws a <see cref="System.NotSupportedException"/>.</returns>
  4435. /// <exception cref="T:System.NotSupportedException">The exception that occurs when this method is called.</exception>
  4436. /// <remarks>
  4437. /// This overload exists to disallow usage of Except with a left data source of type
  4438. /// <see cref="System.Linq.ParallelQuery{TSource}"/> and a right data source of type <see cref="System.Collections.Generic.IEnumerable{TSource}"/>.
  4439. /// Otherwise, the Except operator would appear to be binding to the parallel implementation,
  4440. /// but would in reality bind to the sequential implementation.
  4441. /// </remarks>
  4442. [Obsolete(RIGHT_SOURCE_NOT_PARALLEL_STR)]
  4443. public static ParallelQuery<TSource> Except<TSource>(
  4444. this ParallelQuery<TSource> first, IEnumerable<TSource> second)
  4445. {
  4446. throw new NotSupportedException(SR.GetString(SR.ParallelEnumerable_BinaryOpMustUseAsParallel));
  4447. }
  4448. /// <summary>
  4449. /// Produces the set difference of two parallel sequences by using the
  4450. /// specified IEqualityComparer{T} to compare values.
  4451. /// </summary>
  4452. /// <typeparam name="TSource">The type of the elements of the input sequences.</typeparam>
  4453. /// <param name="first">A sequence whose elements that are not also in <paramref name="second"/> will be returned.</param>
  4454. /// <param name="second">
  4455. /// A sequence whose elements that also occur in the first sequence will cause those elements
  4456. /// to be removed from the returned sequence.
  4457. /// </param>
  4458. /// <param name="comparer">An IEqualityComparer&lt;(Of &lt;(T&gt;)&gt;) to compare values.</param>
  4459. /// <returns>A sequence that contains the set difference of the elements of two sequences.</returns>
  4460. /// <exception cref="T:System.ArgumentNullException">
  4461. /// <paramref name="first"/> or <paramref name="second"/> is a null reference (Nothing in Visual Basic).
  4462. /// </exception>
  4463. public static ParallelQuery<TSource> Except<TSource>(
  4464. this ParallelQuery<TSource> first, ParallelQuery<TSource> second, IEqualityComparer<TSource> comparer)
  4465. {
  4466. if (first == null) throw new ArgumentNullException("first");
  4467. if (second == null) throw new ArgumentNullException("second");
  4468. return new ExceptQueryOperator<TSource>(first, second, comparer);
  4469. }
  4470. /// <summary>
  4471. /// This Except overload should never be called.
  4472. /// This method is marked as obsolete and always throws <see cref="System.NotSupportedException"/> when called.
  4473. /// </summary>
  4474. /// <typeparam name="TSource">This type parameter is not used.</typeparam>
  4475. /// <param name="first">This parameter is not used.</param>
  4476. /// <param name="second">This parameter is not used.</param>
  4477. /// <param name="comparer">This parameter is not used.</param>
  4478. /// <returns>This overload always throws a <see cref="System.NotSupportedException"/>.</returns>
  4479. /// <exception cref="T:System.NotSupportedException">The exception that occurs when this method is called.</exception>
  4480. /// <remarks>
  4481. /// This overload exists to disallow usage of Except with a left data source of type
  4482. /// <see cref="System.Linq.ParallelQuery{TSource}"/> and a right data source of type <see cref="System.Collections.Generic.IEnumerable{TSource}"/>.
  4483. /// Otherwise, the Except operator would appear to be binding to the parallel implementation,
  4484. /// but would in reality bind to the sequential implementation.
  4485. /// </remarks>
  4486. [Obsolete(RIGHT_SOURCE_NOT_PARALLEL_STR)]
  4487. public static ParallelQuery<TSource> Except<TSource>(
  4488. this ParallelQuery<TSource> first, IEnumerable<TSource> second, IEqualityComparer<TSource> comparer)
  4489. {
  4490. throw new NotSupportedException(SR.GetString(SR.ParallelEnumerable_BinaryOpMustUseAsParallel));
  4491. }
  4492. /*===================================================================================
  4493. * DATA TYPE CONVERSION OPERATORS
  4494. *===================================================================================*/
  4495. //-----------------------------------------------------------------------------------
  4496. // For compatability with LINQ. Changes the static type to be less specific if needed.
  4497. //
  4498. /// <summary>
  4499. /// Converts a <see cref="ParallelQuery{T}"/> into an
  4500. /// <see cref="System.Collections.Generic.IEnumerable{T}"/> to force sequential
  4501. /// evaluation of the query.
  4502. /// </summary>
  4503. /// <typeparam name="TSource">The type of the elements of <paramref name="source"/>.</typeparam>
  4504. /// <param name="source">The sequence to type as <see cref="System.Collections.Generic.IEnumerable{T}"/>.</param>
  4505. /// <returns>The input sequence types as <see cref="System.Collections.Generic.IEnumerable{T}"/>.</returns>
  4506. /// <exception cref="T:System.ArgumentNullException">
  4507. /// <paramref name="source"/> is a null reference (Nothing in Visual Basic).
  4508. /// </exception>
  4509. public static IEnumerable<TSource> AsEnumerable<TSource>(this ParallelQuery<TSource> source)
  4510. {
  4511. return AsSequential(source);
  4512. }
  4513. //-----------------------------------------------------------------------------------
  4514. // Simply generates a single-dimensional array containing the elements from the
  4515. // provided enumerable object.
  4516. //
  4517. /// <summary>
  4518. /// Creates an array from a ParallelQuery{T}.
  4519. /// </summary>
  4520. /// <typeparam name="TSource">The type of the elements of <paramref name="source"/>.</typeparam>
  4521. /// <param name="source">A sequence to create an array from.</param>
  4522. /// <returns>An array that contains the elements from the input sequence.</returns>
  4523. /// <exception cref="T:System.ArgumentNullException">
  4524. /// <paramref name="source"/> is a null reference (Nothing in Visual Basic).
  4525. /// </exception>
  4526. /// <exception cref="T:System.AggregateException">
  4527. /// One or more exceptions occurred during the evaluation of the query.
  4528. /// </exception>
  4529. /// <exception cref="T:System.OperationCanceledException">
  4530. /// The query was canceled.
  4531. /// </exception>
  4532. public static TSource[] ToArray<TSource>(this ParallelQuery<TSource> source)
  4533. {
  4534. if (source == null) throw new ArgumentNullException("source");
  4535. QueryOperator<TSource> asOperator = source as QueryOperator<TSource>;
  4536. if (asOperator != null)
  4537. {
  4538. return asOperator.ExecuteAndGetResultsAsArray();
  4539. }
  4540. return ToList<TSource>(source).ToArray<TSource>();
  4541. }
  4542. //-----------------------------------------------------------------------------------
  4543. // The ToList method is similar to the ToArray methods above, except that they return
  4544. // List<TSource> objects. An overload is provided to specify the length, if desired.
  4545. //
  4546. /// <summary>
  4547. /// Creates a List{T} from an ParallelQuery{T}.
  4548. /// </summary>
  4549. /// <typeparam name="TSource">The type of the elements of <paramref name="source"/>.</typeparam>
  4550. /// <param name="source">A sequence to create a List&lt;(Of &lt;(T&gt;)&gt;) from.</param>
  4551. /// <returns>A List&lt;(Of &lt;(T&gt;)&gt;) that contains elements from the input sequence.</returns>
  4552. /// <exception cref="T:System.ArgumentNullException">
  4553. /// <paramref name="source"/> is a null reference (Nothing in Visual Basic).
  4554. /// </exception>
  4555. /// <exception cref="T:System.AggregateException">
  4556. /// One or more exceptions occurred during the evaluation of the query.
  4557. /// </exception>
  4558. /// <exception cref="T:System.OperationCanceledException">
  4559. /// The query was canceled.
  4560. /// </exception>
  4561. public static List<TSource> ToList<TSource>(this ParallelQuery<TSource> source)
  4562. {
  4563. if (source == null) throw new ArgumentNullException("source");
  4564. // Allocate a growable list (optionally passing the length as the initial size).
  4565. List<TSource> list = new List<TSource>();
  4566. IEnumerator<TSource> input;
  4567. QueryOperator<TSource> asOperator = source as QueryOperator<TSource>;
  4568. if (asOperator != null)
  4569. {
  4570. if (asOperator.OrdinalIndexState == OrdinalIndexState.Indexible && asOperator.OutputOrdered)
  4571. {
  4572. // If the query is indexible and the output is ordered, we will use the array-based merge.
  4573. // That way, we avoid the ordering overhead. Due to limitations of the List<> class, the
  4574. // most efficient solution seems to be to first dump all results into the array, and then
  4575. // copy them over into a List<>.
  4576. //
  4577. // The issue is that we cannot efficiently construct a List<> with a fixed size. We can
  4578. // construct a List<> with a fixed *capacity*, but we still need to call Add() N times
  4579. // in order to be able to index into the List<>.
  4580. return new List<TSource>(ToArray<TSource>(source));
  4581. }
  4582. // We will enumerate the list w/out pipelining.
  4583. // @PERF: there are likely some cases, e.g. for very large data sets,
  4584. // where we want to use pipelining for this operation. It can reduce memory
  4585. // usage since, as we enumerate w/ pipelining off, we're already accumulating
  4586. // results into a buffer. As a matter of fact, there's probably a way we can
  4587. // just directly use that buffer below instead of creating a new list.
  4588. input = asOperator.GetEnumerator(ParallelMergeOptions.FullyBuffered);
  4589. }
  4590. else
  4591. {
  4592. input = source.GetEnumerator();
  4593. }
  4594. // Now, accumulate the results into a dynamically sized list, stopping if we reach
  4595. // the (optionally specified) maximum length.
  4596. Contract.Assert(input != null);
  4597. using (input)
  4598. {
  4599. while (input.MoveNext())
  4600. {
  4601. list.Add(input.Current);
  4602. }
  4603. }
  4604. return list;
  4605. }
  4606. //-----------------------------------------------------------------------------------
  4607. // ToDictionary constructs a dictionary from an instance of ParallelQuery.
  4608. // Each element in the enumerable is converted to a (key,value) pair using a pair
  4609. // of lambda expressions specified by the caller. Different elements must produce
  4610. // different keys or else ArgumentException is thrown.
  4611. //
  4612. /// <summary>
  4613. /// Creates a Dictionary{TKey,TValue} from a ParallelQuery{T} according to
  4614. /// a specified key selector function.
  4615. /// </summary>
  4616. /// <typeparam name="TSource">The type of the elements of <paramref name="source"/>.</typeparam>
  4617. /// <typeparam name="TKey">The type of the key returned by <paramref name="keySelector"/>.</typeparam>
  4618. /// <param name="source">A sequence to create a Dictionary&lt;(Of &lt;(TKey, TValue&gt;)&gt;) from.</param>
  4619. /// <param name="keySelector">A function to extract a key from each element.</param>
  4620. /// <returns>A Dictionary&lt;(Of &lt;(TKey, TValue&gt;)&gt;) that contains keys and values.</returns>
  4621. /// <exception cref="T:System.ArgumentNullException">
  4622. /// <paramref name="source"/> or <paramref name="keySelector"/> is a null reference (Nothing in Visual Basic).
  4623. /// </exception>
  4624. /// <exception cref="T:System.AggregateException">
  4625. /// <paramref name="keySelector"/> produces a key that is a null reference (Nothing in Visual Basic).
  4626. /// -or-
  4627. /// <paramref name="keySelector"/> produces duplicate keys for two elements.
  4628. /// -or-
  4629. /// One or more exceptions occurred during the evaluation of the query.
  4630. /// </exception>
  4631. /// <exception cref="T:System.OperationCanceledException">
  4632. /// The query was canceled.
  4633. /// </exception>
  4634. public static Dictionary<TKey, TSource> ToDictionary<TSource, TKey>(
  4635. this ParallelQuery<TSource> source, Func<TSource, TKey> keySelector)
  4636. {
  4637. return ToDictionary(source, keySelector, EqualityComparer<TKey>.Default);
  4638. }
  4639. /// <summary>
  4640. /// Creates a Dictionary{TKey,TValue} from a ParallelQuery{T} according to a
  4641. /// specified key selector function and key comparer.
  4642. /// </summary>
  4643. /// <typeparam name="TSource">The type of the elements of <paramref name="source"/>.</typeparam>
  4644. /// <typeparam name="TKey">The type of the key returned by <paramref name="keySelector"/>.</typeparam>
  4645. /// <param name="source">A sequence to create a Dictionary&lt;(Of &lt;(TKey, TValue&gt;)&gt;) from.</param>
  4646. /// <param name="keySelector">A function to extract a key from each element.</param>
  4647. /// <param name="comparer">An IEqualityComparer&lt;(Of &lt;(T&gt;)&gt;) to compare keys.</param>
  4648. /// <returns>A Dictionary&lt;(Of &lt;(TKey, TValue&gt;)&gt;) that contains keys and values.</returns>
  4649. /// <exception cref="T:System.ArgumentNullException">
  4650. /// <paramref name="source"/> or <paramref name="keySelector"/> is a null reference (Nothing in Visual Basic).
  4651. /// </exception>
  4652. /// <exception cref="T:System.AggregateException">
  4653. /// <paramref name="keySelector"/> produces a key that is a null reference (Nothing in Visual Basic).
  4654. /// -or-
  4655. /// <paramref name="keySelector"/> produces duplicate keys for two elements.
  4656. /// -or-
  4657. /// One or more exceptions occurred during the evaluation of the query.
  4658. /// </exception>
  4659. /// <exception cref="T:System.OperationCanceledException">
  4660. /// The query was canceled.
  4661. /// </exception>
  4662. public static Dictionary<TKey, TSource> ToDictionary<TSource, TKey>(
  4663. this ParallelQuery<TSource> source, Func<TSource, TKey> keySelector, IEqualityComparer<TKey> comparer)
  4664. {
  4665. if (source == null) throw new ArgumentNullException("source");
  4666. if (keySelector == null) throw new ArgumentNullException("keySelector");
  4667. // comparer may be null. In that case, the Dictionary constructor will use the default comparer.
  4668. Dictionary<TKey, TSource> result = new Dictionary<TKey, TSource>(comparer);
  4669. QueryOperator<TSource> op = source as QueryOperator<TSource>;
  4670. IEnumerator<TSource> input = (op == null) ? source.GetEnumerator() : op.GetEnumerator(ParallelMergeOptions.FullyBuffered, true);
  4671. using(input)
  4672. {
  4673. while (input.MoveNext())
  4674. {
  4675. TKey key;
  4676. TSource val = input.Current;
  4677. try
  4678. {
  4679. key = keySelector(val);
  4680. result.Add(key, val);
  4681. }
  4682. catch (ThreadAbortException)
  4683. {
  4684. // Do not wrap ThreadAbortExceptions
  4685. throw;
  4686. }
  4687. catch (Exception ex)
  4688. {
  4689. throw new AggregateException(ex);
  4690. }
  4691. }
  4692. }
  4693. return result;
  4694. }
  4695. /// <summary>
  4696. /// Creates a Dictionary{TKey,TValue} from a ParallelQuery{T} according to specified
  4697. /// key selector and element selector functions.
  4698. /// </summary>
  4699. /// <typeparam name="TSource">The type of the elements of <paramref name="source"/>.</typeparam>
  4700. /// <typeparam name="TKey">The type of the key returned by <paramref name="keySelector"/>.</typeparam>
  4701. /// <typeparam name="TElement">The type of the value returned by <paramref name="elementSelector"/>.</typeparam>
  4702. /// <param name="source">A sequence to create a Dictionary&lt;(Of &lt;(TKey, TValue&gt;)&gt;) from.</param>
  4703. /// <param name="keySelector">A function to extract a key from each element.</param>
  4704. /// <param name="elementSelector">
  4705. /// A transform function to produce a result element value from each element.
  4706. /// </param>
  4707. /// <returns>
  4708. /// A Dictionary&lt;(Of &lt;(TKey, TValue&gt;)&gt;) that contains values of type <typeparamref name="TElement"/>
  4709. /// selected from the input sequence
  4710. /// </returns>
  4711. /// <exception cref="T:System.ArgumentNullException">
  4712. /// <paramref name="source"/> or <paramref name="keySelector"/> or <paramref name="elementSelector"/> is a null reference (Nothing in Visual Basic).
  4713. /// </exception>
  4714. /// <exception cref="T:System.AggregateException">
  4715. /// <paramref name="keySelector"/> produces a key that is a null reference (Nothing in Visual Basic).
  4716. /// -or-
  4717. /// <paramref name="keySelector"/> produces duplicate keys for two elements.
  4718. /// -or-
  4719. /// One or more exceptions occurred during the evaluation of the query.
  4720. /// </exception>
  4721. /// <exception cref="T:System.OperationCanceledException">
  4722. /// The query was canceled.
  4723. /// </exception>
  4724. public static Dictionary<TKey, TElement> ToDictionary<TSource, TKey, TElement>(
  4725. this ParallelQuery<TSource> source, Func<TSource, TKey> keySelector, Func<TSource, TElement> elementSelector)
  4726. {
  4727. return ToDictionary(source, keySelector, elementSelector, EqualityComparer<TKey>.Default);
  4728. }
  4729. /// <summary>
  4730. /// Creates a Dictionary{TKey,TValue from a ParallelQuery{T} according to a
  4731. /// specified key selector function, a comparer, and an element selector function.
  4732. /// </summary>
  4733. /// <typeparam name="TSource">The type of the elements of <paramref name="source"/>.</typeparam>
  4734. /// <typeparam name="TKey">The type of the key returned by <paramref name="keySelector"/>.</typeparam>
  4735. /// <typeparam name="TElement">The type of the value returned by <paramref name="elementSelector"/>.</typeparam>
  4736. /// <param name="source">A sequence to create a Dictionary&lt;(Of &lt;(TKey, TValue&gt;)&gt;) from.</param>
  4737. /// <param name="keySelector">A function to extract a key from each element.</param>
  4738. /// <param name="elementSelector">A transform function to produce a result element
  4739. /// value from each element.</param>
  4740. /// <param name="comparer">An IEqualityComparer&lt;(Of &lt;(T&gt;)&gt;) to compare keys.</param>
  4741. /// <returns>
  4742. /// A Dictionary&lt;(Of &lt;(TKey, TValue&gt;)&gt;) that contains values of type <typeparamref name="TElement"/>
  4743. /// selected from the input sequence
  4744. /// </returns>
  4745. /// <exception cref="T:System.ArgumentNullException">
  4746. /// <paramref name="source"/> or <paramref name="keySelector"/> or <paramref name="elementSelector"/> is a null reference (Nothing in Visual Basic).
  4747. /// </exception>
  4748. /// <exception cref="T:System.AggregateException">
  4749. /// <paramref name="keySelector"/> produces a key that is a null reference (Nothing in Visual Basic).
  4750. /// -or-
  4751. /// <paramref name="keySelector"/> produces duplicate keys for two elements.
  4752. /// -or-
  4753. /// One or more exceptions occurred during the evaluation of the query.
  4754. /// </exception>
  4755. /// <exception cref="T:System.OperationCanceledException">
  4756. /// The query was canceled.
  4757. /// </exception>
  4758. public static Dictionary<TKey, TElement> ToDictionary<TSource, TKey, TElement>(
  4759. this ParallelQuery<TSource> source, Func<TSource, TKey> keySelector, Func<TSource, TElement> elementSelector, IEqualityComparer<TKey> comparer)
  4760. {
  4761. if (source == null) throw new ArgumentNullException("source");
  4762. if (keySelector == null) throw new ArgumentNullException("keySelector");
  4763. if (elementSelector == null) throw new ArgumentNullException("elementSelector");
  4764. // comparer may be null. In that case, the Dictionary constructor will use the default comparer.
  4765. Dictionary<TKey, TElement> result = new Dictionary<TKey, TElement>(comparer);
  4766. QueryOperator<TSource> op = source as QueryOperator<TSource>;
  4767. IEnumerator<TSource> input = (op == null) ? source.GetEnumerator() : op.GetEnumerator(ParallelMergeOptions.FullyBuffered, true);
  4768. using(input)
  4769. {
  4770. while (input.MoveNext())
  4771. {
  4772. TSource src = input.Current;
  4773. try
  4774. {
  4775. result.Add(keySelector(src), elementSelector(src));
  4776. }
  4777. catch (ThreadAbortException)
  4778. {
  4779. // Do not wrap ThreadAbortExceptions
  4780. throw;
  4781. }
  4782. catch(Exception ex)
  4783. {
  4784. throw new AggregateException(ex);
  4785. }
  4786. }
  4787. }
  4788. return result;
  4789. }
  4790. //-----------------------------------------------------------------------------------
  4791. // ToLookup constructs a lookup from an instance of ParallelQuery.
  4792. // Each element in the enumerable is converted to a (key,value) pair using a pair
  4793. // of lambda expressions specified by the caller. Multiple elements are allowed
  4794. // to produce the same key.
  4795. //
  4796. /// <summary>
  4797. /// Creates an ILookup{TKey,T} from a ParallelQuery{T} according to a specified key selector function.
  4798. /// </summary>
  4799. /// <typeparam name="TSource">The type of elements of <paramref name="source"/>.</typeparam>
  4800. /// <typeparam name="TKey">The type of the key returned by <paramref name="keySelector"/>.</typeparam>
  4801. /// <param name="source">The sequence to create a Lookup&lt;(Of &lt;(TKey, TElement&gt;)&gt;) from.</param>
  4802. /// <param name="keySelector">A function to extract a key from each element.</param>
  4803. /// <returns>A Lookup&lt;(Of &lt;(TKey, TElement&gt;)&gt;) that contains keys and values.</returns>
  4804. /// <exception cref="T:System.ArgumentNullException">
  4805. /// <paramref name="source"/> or <paramref name="keySelector"/> is a null reference (Nothing in Visual Basic).
  4806. /// </exception>
  4807. /// <exception cref="T:System.AggregateException">
  4808. /// One or more exceptions occurred during the evaluation of the query.
  4809. /// </exception>
  4810. /// <exception cref="T:System.OperationCanceledException">
  4811. /// The query was canceled.
  4812. /// </exception>
  4813. public static ILookup<TKey, TSource> ToLookup<TSource, TKey>(
  4814. this ParallelQuery<TSource> source, Func<TSource, TKey> keySelector)
  4815. {
  4816. return ToLookup(source, keySelector, EqualityComparer<TKey>.Default);
  4817. }
  4818. /// <summary>
  4819. /// Creates an ILookup{TKey,T} from a ParallelQuery{T} according to a specified
  4820. /// key selector function and key comparer.
  4821. /// </summary>
  4822. /// <typeparam name="TSource">The type of elements of <paramref name="source"/>.</typeparam>
  4823. /// <typeparam name="TKey">The type of the key returned by <paramref name="keySelector"/>.</typeparam>
  4824. /// <param name="source">The sequence to create a Lookup&lt;(Of &lt;(TKey, TElement&gt;)&gt;) from.</param>
  4825. /// <param name="keySelector">A function to extract a key from each element.</param>
  4826. /// <param name="comparer">An IEqualityComparer&lt;(Of &lt;(T&gt;)&gt;) to compare keys.</param>
  4827. /// <returns>A Lookup&lt;(Of &lt;(TKey, TElement&gt;)&gt;) that contains keys and values.</returns>
  4828. /// <exception cref="T:System.ArgumentNullException">
  4829. /// <paramref name="source"/> or <paramref name="keySelector"/> or is a null reference (Nothing in Visual Basic).
  4830. /// </exception>
  4831. /// <exception cref="T:System.AggregateException">
  4832. /// One or more exceptions occurred during the evaluation of the query.
  4833. /// </exception>
  4834. /// <exception cref="T:System.OperationCanceledException">
  4835. /// The query was canceled.
  4836. /// </exception>
  4837. public static ILookup<TKey, TSource> ToLookup<TSource, TKey>(
  4838. this ParallelQuery<TSource> source, Func<TSource, TKey> keySelector, IEqualityComparer<TKey> comparer)
  4839. {
  4840. if (source == null) throw new ArgumentNullException("source");
  4841. if (keySelector == null) throw new ArgumentNullException("keySelector");
  4842. // comparer may be null, in which case we use the default comparer.
  4843. comparer = comparer ?? EqualityComparer<TKey>.Default;
  4844. ParallelQuery<IGrouping<TKey, TSource>> groupings = source.GroupBy(keySelector, comparer);
  4845. Parallel.Lookup<TKey, TSource> lookup = new Parallel.Lookup<TKey, TSource>(comparer);
  4846. Contract.Assert(groupings is QueryOperator<IGrouping<TKey, TSource>>);
  4847. QueryOperator<IGrouping<TKey, TSource>> op = groupings as QueryOperator<IGrouping<TKey, TSource>>;
  4848. IEnumerator<IGrouping<TKey, TSource>> input = (op == null) ? groupings.GetEnumerator() : op.GetEnumerator(ParallelMergeOptions.FullyBuffered);
  4849. using(input)
  4850. {
  4851. while (input.MoveNext())
  4852. {
  4853. lookup.Add(input.Current);
  4854. }
  4855. }
  4856. return lookup;
  4857. }
  4858. /// <summary>
  4859. /// Creates an ILookup{TKey,TElement} from a ParallelQuery{T} according to specified
  4860. /// key selector and element selector functions.
  4861. /// </summary>
  4862. /// <typeparam name="TSource">The type of elements of <paramref name="source"/>.</typeparam>
  4863. /// <typeparam name="TKey">The type of the key returned by <paramref name="keySelector"/>.</typeparam>
  4864. /// <typeparam name="TElement">The type of the value returned by <paramref name="elementSelector"/>.</typeparam>
  4865. /// <param name="source">The sequence to create a Lookup&lt;(Of &lt;(TKey, TElement&gt;)&gt;) from.</param>
  4866. /// <param name="keySelector">A function to extract a key from each element.</param>
  4867. /// <param name="elementSelector">
  4868. /// A transform function to produce a result element value from each element.
  4869. /// </param>
  4870. /// <returns>
  4871. /// A Lookup&lt;(Of &lt;(TKey, TElement&gt;)&gt;) that contains values of type TElement
  4872. /// selected from the input sequence.
  4873. /// </returns>
  4874. /// <exception cref="T:System.ArgumentNullException">
  4875. /// <paramref name="source"/> or <paramref name="keySelector"/> or <paramref name="elementSelector"/> is a null reference (Nothing in Visual Basic).
  4876. /// </exception>
  4877. /// <exception cref="T:System.AggregateException">
  4878. /// One or more exceptions occurred during the evaluation of the query.
  4879. /// </exception>
  4880. /// <exception cref="T:System.OperationCanceledException">
  4881. /// The query was canceled.
  4882. /// </exception>
  4883. public static ILookup<TKey, TElement> ToLookup<TSource, TKey, TElement>(
  4884. this ParallelQuery<TSource> source, Func<TSource, TKey> keySelector, Func<TSource, TElement> elementSelector)
  4885. {
  4886. return ToLookup(source, keySelector, elementSelector, EqualityComparer<TKey>.Default);
  4887. }
  4888. /// <summary>
  4889. /// Creates an ILookup{TKey,TElement} from a ParallelQuery{T} according to
  4890. /// a specified key selector function, a comparer and an element selector function.
  4891. /// </summary>
  4892. /// <typeparam name="TSource">The type of elements of <paramref name="source"/>.</typeparam>
  4893. /// <typeparam name="TKey">The type of the key returned by <paramref name="keySelector"/>.</typeparam>
  4894. /// <typeparam name="TElement">The type of the value returned by <paramref name="elementSelector"/>.</typeparam>
  4895. /// <param name="source">The sequence to create a Lookup&lt;(Of &lt;(TKey, TElement&gt;)&gt;) from.</param>
  4896. /// <param name="keySelector">A function to extract a key from each element.</param>
  4897. /// <param name="elementSelector">
  4898. /// A transform function to produce a result element value from each element.
  4899. /// </param>
  4900. /// <param name="comparer">An IEqualityComparer&lt;(Of &lt;(T&gt;)&gt;) to compare keys.</param>
  4901. /// <returns>
  4902. /// A Lookup&lt;(Of &lt;(TKey, TElement&gt;)&gt;) that contains values of type TElement selected
  4903. /// from the input sequence.
  4904. /// </returns>
  4905. /// <exception cref="T:System.ArgumentNullException">
  4906. /// <paramref name="source"/> or <paramref name="keySelector"/> or <paramref name="elementSelector"/> is a null reference (Nothing in Visual Basic).
  4907. /// </exception>
  4908. /// <exception cref="T:System.AggregateException">
  4909. /// One or more exceptions occurred during the evaluation of the query.
  4910. /// </exception>
  4911. /// <exception cref="T:System.OperationCanceledException">
  4912. /// The query was canceled.
  4913. /// </exception>
  4914. public static ILookup<TKey, TElement> ToLookup<TSource, TKey, TElement>(
  4915. this ParallelQuery<TSource> source, Func<TSource, TKey> keySelector, Func<TSource, TElement> elementSelector, IEqualityComparer<TKey> comparer)
  4916. {
  4917. if (source == null) throw new ArgumentNullException("source");
  4918. if (keySelector == null) throw new ArgumentNullException("keySelector");
  4919. if (elementSelector == null) throw new ArgumentNullException("elementSelector");
  4920. // comparer may be null, in which case we use the default comparer.
  4921. comparer = comparer ?? EqualityComparer<TKey>.Default;
  4922. ParallelQuery<IGrouping<TKey, TElement>> groupings = source.GroupBy(keySelector, elementSelector, comparer);
  4923. Parallel.Lookup<TKey, TElement> lookup = new Parallel.Lookup<TKey, TElement>(comparer);
  4924. Contract.Assert(groupings is QueryOperator<IGrouping<TKey, TElement>>);
  4925. QueryOperator<IGrouping<TKey, TElement>> op = groupings as QueryOperator<IGrouping<TKey, TElement>>;
  4926. IEnumerator<IGrouping<TKey, TElement>> input = (op == null) ? groupings.GetEnumerator() : op.GetEnumerator(ParallelMergeOptions.FullyBuffered);
  4927. using(input)
  4928. {
  4929. while (input.MoveNext())
  4930. {
  4931. lookup.Add(input.Current);
  4932. }
  4933. }
  4934. return lookup;
  4935. }
  4936. /*===================================================================================
  4937. * MISCELLANEOUS OPERATORS
  4938. *===================================================================================*/
  4939. //-----------------------------------------------------------------------------------
  4940. // Reverses the input.
  4941. //
  4942. /// <summary>
  4943. /// Inverts the order of the elements in a parallel sequence.
  4944. /// </summary>
  4945. /// <typeparam name="TSource">The type of the elements of <paramref name="source"/>.</typeparam>
  4946. /// <param name="source">A sequence of values to reverse.</param>
  4947. /// <returns>A sequence whose elements correspond to those of the input sequence in reverse order.</returns>
  4948. /// <exception cref="T:System.ArgumentNullException">
  4949. /// <paramref name="source"/> is a null reference (Nothing in Visual Basic).
  4950. /// </exception>
  4951. public static ParallelQuery<TSource> Reverse<TSource>(this ParallelQuery<TSource> source)
  4952. {
  4953. if (source == null) throw new ArgumentNullException("source");
  4954. return new ReverseQueryOperator<TSource>(source);
  4955. }
  4956. //-----------------------------------------------------------------------------------
  4957. // Both OfType and Cast convert a weakly typed stream to a strongly typed one:
  4958. // the difference is that OfType filters out elements that aren't of the given type,
  4959. // while Cast forces the cast, possibly resulting in InvalidCastExceptions.
  4960. //
  4961. /// <summary>
  4962. /// Filters the elements of a ParallelQuery based on a specified type.
  4963. /// </summary>
  4964. /// <typeparam name="TResult">The type to filter the elements of the sequence on.</typeparam>
  4965. /// <param name="source">The sequence whose elements to filter.</param>
  4966. /// <returns>A sequence that contains elements from the input sequence of type <typeparamref name="TResult"/>.</returns>
  4967. /// <exception cref="T:System.ArgumentNullException">
  4968. /// <paramref name="source"/> is a null reference (Nothing in Visual Basic).
  4969. /// </exception>
  4970. public static ParallelQuery<TResult> OfType<TResult>(this ParallelQuery source)
  4971. {
  4972. if (source == null) throw new ArgumentNullException("source");
  4973. return source.OfType<TResult>();
  4974. }
  4975. /// <summary>
  4976. /// Converts the elements of a ParallelQuery to the specified type.
  4977. /// </summary>
  4978. /// <typeparam name="TResult">The type to convert the elements of <paramref name="source"/> to.</typeparam>
  4979. /// <param name="source">The sequence that contains the elements to be converted.</param>
  4980. /// <returns>
  4981. /// A sequence that contains each element of the source sequence converted to the specified type.
  4982. /// </returns>
  4983. /// <exception cref="T:System.ArgumentNullException">
  4984. /// <paramref name="source"/> is a null reference (Nothing in Visual Basic).
  4985. /// </exception>
  4986. public static ParallelQuery<TResult> Cast<TResult>(this ParallelQuery source)
  4987. {
  4988. return source.Cast<TResult>();
  4989. }
  4990. //-----------------------------------------------------------------------------------
  4991. // Helper method used by First, FirstOrDefault, Last, LastOrDefault, Single, and
  4992. // SingleOrDefault below. This takes a query operator, gets the first item (and
  4993. // either checks or asserts there is at most one item in the source), and returns it.
  4994. // If there are no elements, the method either throws an exception or, if
  4995. // defaultIfEmpty is true, returns a default value.
  4996. //
  4997. // Arguments:
  4998. // queryOp - the query operator to enumerate (for the single element)
  4999. // throwIfTwo - whether to throw an exception (true) or assert (false) that
  5000. // there is no more than one element in the source
  5001. // defaultIfEmpty - whether to return a default value (true) or throw an
  5002. // exception if the output of the query operator is empty
  5003. //
  5004. private static TSource GetOneWithPossibleDefault<TSource>(
  5005. QueryOperator<TSource> queryOp, bool throwIfTwo, bool defaultIfEmpty)
  5006. {
  5007. Contract.Assert(queryOp != null, "expected query operator");
  5008. using (IEnumerator<TSource> e = queryOp.GetEnumerator(ParallelMergeOptions.FullyBuffered))
  5009. {
  5010. if (e.MoveNext())
  5011. {
  5012. TSource current = e.Current;
  5013. // Some operators need to do a runtime, retail check for more than one element.
  5014. // Others can simply ----sert that there was only one.
  5015. if (throwIfTwo)
  5016. {
  5017. if (e.MoveNext())
  5018. {
  5019. throw new InvalidOperationException(SR.GetString(SR.MoreThanOneMatch));
  5020. }
  5021. }
  5022. else
  5023. {
  5024. Contract.Assert(!e.MoveNext(), "expected only a single element");
  5025. }
  5026. return current;
  5027. }
  5028. }
  5029. if (defaultIfEmpty)
  5030. {
  5031. return default(TSource);
  5032. }
  5033. else
  5034. {
  5035. throw new InvalidOperationException(SR.GetString(SR.NoElements));
  5036. }
  5037. }
  5038. //-----------------------------------------------------------------------------------
  5039. // First simply returns the first element from the data source; if the predicate
  5040. // overload is used, the first element satisfying the predicate is returned.
  5041. // An exception is thrown for empty data sources. Alternatively, the FirstOrDefault
  5042. // method can be used which returns defualt(T) if empty (or no elements satisfy the
  5043. // predicate).
  5044. //
  5045. /// <summary>
  5046. /// Returns the first element of a parallel sequence.</summary>
  5047. /// <typeparam name="TSource">The type of the elements of <paramref name="source"/>.</typeparam>
  5048. /// <param name="source">The sequence to return the first element of.</param>
  5049. /// <returns>The first element in the specified sequence.</returns>
  5050. /// <exception cref="T:System.ArgumentNullException">
  5051. /// <paramref name="source"/> is a null reference (Nothing in Visual Basic).
  5052. /// </exception>
  5053. /// <exception cref="T:System.InvalidOperationException">
  5054. /// <paramref name="source"/> contains no elements.
  5055. /// </exception>
  5056. /// <exception cref="T:System.AggregateException">
  5057. /// One or more exceptions occurred during the evaluation of the query.
  5058. /// </exception>
  5059. /// <exception cref="T:System.OperationCanceledException">
  5060. /// The query was canceled.
  5061. /// </exception>
  5062. public static TSource First<TSource>(this ParallelQuery<TSource> source)
  5063. {
  5064. // @PERF: optimize for seekable data sources. E.g. if an array, we can
  5065. // seek directly to the 0th element.
  5066. if (source == null) throw new ArgumentNullException("source");
  5067. FirstQueryOperator<TSource> queryOp = new FirstQueryOperator<TSource>(source, null);
  5068. // If in conservative mode and a premature merge would be inserted by the First operator,
  5069. // run the whole query sequentially.
  5070. QuerySettings settings = queryOp.SpecifiedQuerySettings.WithDefaults();
  5071. if (queryOp.LimitsParallelism && settings.ExecutionMode != ParallelExecutionMode.ForceParallelism)
  5072. {
  5073. IEnumerable<TSource> childAsSequential = queryOp.Child.AsSequentialQuery(settings.CancellationState.ExternalCancellationToken);
  5074. IEnumerable<TSource> childWithCancelChecks = CancellableEnumerable.Wrap(childAsSequential, settings.CancellationState.ExternalCancellationToken);
  5075. return ExceptionAggregator.WrapEnumerable(childWithCancelChecks, settings.CancellationState)
  5076. .First();
  5077. }
  5078. return GetOneWithPossibleDefault(queryOp, false, false);
  5079. }
  5080. /// <summary>
  5081. /// Returns the first element in a parallel sequence that satisfies a specified condition.
  5082. /// </summary>
  5083. /// <remarks>There's a temporary difference from LINQ to Objects, this does not throw
  5084. /// ArgumentNullException when the predicate is null.</remarks>
  5085. /// <typeparam name="TSource">The type of the elements of <paramref name="source"/>.</typeparam>
  5086. /// <param name="source">The sequence to return an element from.</param>
  5087. /// <param name="predicate">A function to test each element for a condition.</param>
  5088. /// <returns>The first element in the sequence that passes the test in the specified predicate function.</returns>
  5089. /// <exception cref="T:System.ArgumentNullException">
  5090. /// <paramref name="source"/> or <paramref name="predicate"/> is a null reference (Nothing in Visual Basic).
  5091. /// </exception>
  5092. /// <exception cref="T:System.InvalidOperationException">
  5093. /// No element in <paramref name="source"/> satisfies the condition in <paramref name="predicate"/>.
  5094. /// </exception>
  5095. /// <exception cref="T:System.AggregateException">
  5096. /// One or more exceptions occurred during the evaluation of the query.
  5097. /// </exception>
  5098. /// <exception cref="T:System.OperationCanceledException">
  5099. /// The query was canceled.
  5100. /// </exception>
  5101. public static TSource First<TSource>(this ParallelQuery<TSource> source, Func<TSource, bool> predicate)
  5102. {
  5103. if (source == null) throw new ArgumentNullException("source");
  5104. if (predicate == null) throw new ArgumentNullException("predicate");
  5105. FirstQueryOperator<TSource> queryOp = new FirstQueryOperator<TSource>(source, predicate);
  5106. // If in conservative mode and a premature merge would be inserted by the First operator,
  5107. // run the whole query sequentially.
  5108. QuerySettings settings = queryOp.SpecifiedQuerySettings.WithDefaults();
  5109. if (queryOp.LimitsParallelism && settings.ExecutionMode != ParallelExecutionMode.ForceParallelism)
  5110. {
  5111. IEnumerable<TSource> childAsSequential = queryOp.Child.AsSequentialQuery(settings.CancellationState.ExternalCancellationToken);
  5112. IEnumerable<TSource> childWithCancelChecks = CancellableEnumerable.Wrap(childAsSequential, settings.CancellationState.ExternalCancellationToken);
  5113. return ExceptionAggregator.WrapEnumerable(childWithCancelChecks, settings.CancellationState)
  5114. .First(ExceptionAggregator.WrapFunc<TSource, bool>(predicate, settings.CancellationState));
  5115. }
  5116. return GetOneWithPossibleDefault(queryOp, false, false);
  5117. }
  5118. /// <summary>
  5119. /// Returns the first element of a parallel sequence, or a default value if the
  5120. /// sequence contains no elements.
  5121. /// </summary>
  5122. /// <typeparam name="TSource">The type of the elements of <paramref name="source"/>.</typeparam>
  5123. /// <param name="source">The sequence to return the first element of.</param>
  5124. /// <returns>
  5125. /// default(<B>TSource</B>) if <paramref name="source"/> is empty; otherwise, the first element in <paramref name="source"/>.
  5126. /// </returns>
  5127. /// <exception cref="T:System.ArgumentNullException">
  5128. /// <paramref name="source"/> is a null reference (Nothing in Visual Basic).
  5129. /// </exception>
  5130. /// <exception cref="T:System.AggregateException">
  5131. /// One or more exceptions occurred during the evaluation of the query.
  5132. /// </exception>
  5133. /// <exception cref="T:System.OperationCanceledException">
  5134. /// The query was canceled.
  5135. /// </exception>
  5136. public static TSource FirstOrDefault<TSource>(this ParallelQuery<TSource> source)
  5137. {
  5138. if (source == null) throw new ArgumentNullException("source");
  5139. // @PERF: optimize for seekable data sources. E.g. if an array, we can
  5140. // seek directly to the 0th element.
  5141. FirstQueryOperator<TSource> queryOp = new FirstQueryOperator<TSource>(source, null);
  5142. // If in conservative mode and a premature merge would be inserted by the First operator,
  5143. // run the whole query sequentially.
  5144. QuerySettings settings = queryOp.SpecifiedQuerySettings.WithDefaults();
  5145. if (queryOp.LimitsParallelism
  5146. && settings.ExecutionMode != ParallelExecutionMode.ForceParallelism)
  5147. {
  5148. IEnumerable<TSource> childAsSequential = queryOp.Child.AsSequentialQuery(settings.CancellationState.ExternalCancellationToken);
  5149. IEnumerable<TSource> childWithCancelChecks = CancellableEnumerable.Wrap(childAsSequential, settings.CancellationState.ExternalCancellationToken);
  5150. return ExceptionAggregator.WrapEnumerable(childWithCancelChecks,
  5151. settings.CancellationState).FirstOrDefault();
  5152. }
  5153. return GetOneWithPossibleDefault(queryOp, false, true);
  5154. }
  5155. /// <summary>
  5156. /// Returns the first element of the parallel sequence that satisfies a condition or a
  5157. /// default value if no such element is found.
  5158. /// </summary>
  5159. /// <remarks>There's a temporary difference from LINQ to Objects, this does not throw
  5160. /// ArgumentNullException when the predicate is null.</remarks>
  5161. /// <typeparam name="TSource">The type of the elements of <paramref name="source"/>.</typeparam>
  5162. /// <param name="source">The sequence to return an element from.</param>
  5163. /// <param name="predicate">A function to test each element for a condition.</param>
  5164. /// <returns>
  5165. /// default(<B>TSource</B>) if <paramref name="source"/> is empty or if no element passes the test
  5166. /// specified by <B>predicate</B>; otherwise, the first element in <paramref name="source"/> that
  5167. /// passes the test specified by <B>predicate</B>.
  5168. /// </returns>
  5169. /// <exception cref="T:System.ArgumentNullException">
  5170. /// <paramref name="source"/> or <paramref name="predicate"/> is a null reference (Nothing in Visual Basic).
  5171. /// </exception>
  5172. /// <exception cref="T:System.AggregateException">
  5173. /// One or more exceptions occurred during the evaluation of the query.
  5174. /// </exception>
  5175. /// <exception cref="T:System.OperationCanceledException">
  5176. /// The query was canceled.
  5177. /// </exception>
  5178. public static TSource FirstOrDefault<TSource>(this ParallelQuery<TSource> source, Func<TSource, bool> predicate)
  5179. {
  5180. if (source == null) throw new ArgumentNullException("source");
  5181. if (predicate == null) throw new ArgumentNullException("predicate");
  5182. FirstQueryOperator<TSource> queryOp = new FirstQueryOperator<TSource>(source, predicate);
  5183. // If in conservative mode and a premature merge would be inserted by the First operator,
  5184. // run the whole query sequentially.
  5185. QuerySettings settings = queryOp.SpecifiedQuerySettings.WithDefaults();
  5186. if (queryOp.LimitsParallelism
  5187. && settings.ExecutionMode != ParallelExecutionMode.ForceParallelism)
  5188. {
  5189. IEnumerable<TSource> childAsSequential = queryOp.Child.AsSequentialQuery(settings.CancellationState.ExternalCancellationToken);
  5190. IEnumerable<TSource> childWithCancelChecks = CancellableEnumerable.Wrap(childAsSequential, settings.CancellationState.ExternalCancellationToken);
  5191. return ExceptionAggregator.WrapEnumerable(
  5192. childWithCancelChecks, settings.CancellationState)
  5193. .FirstOrDefault(ExceptionAggregator.WrapFunc<TSource, bool>(predicate, settings.CancellationState));
  5194. }
  5195. return GetOneWithPossibleDefault(queryOp, false, true);
  5196. }
  5197. //-----------------------------------------------------------------------------------
  5198. // Last simply returns the last element from the data source; if the predicate
  5199. // overload is used, the last element satisfying the predicate is returned.
  5200. // An exception is thrown for empty data sources. Alternatively, the LastOrDefault
  5201. // method can be used which returns defualt(T) if empty (or no elements satisfy the
  5202. // predicate).
  5203. //
  5204. /// <summary>
  5205. /// Returns the last element of a parallel sequence.</summary>
  5206. /// <typeparam name="TSource">The type of the elements of <paramref name="source"/>.</typeparam>
  5207. /// <param name="source">The sequence to return the last element from.</param>
  5208. /// <returns>The value at the last position in the source sequence.</returns>
  5209. /// <exception cref="T:System.ArgumentNullException">
  5210. /// <paramref name="source"/> is a null reference (Nothing in Visual Basic).
  5211. /// </exception>
  5212. /// <exception cref="T:System.InvalidOperationException">
  5213. /// <paramref name="source"/> contains no elements.
  5214. /// </exception>
  5215. /// <exception cref="T:System.AggregateException">
  5216. /// One or more exceptions occurred during the evaluation of the query.
  5217. /// </exception>
  5218. /// <exception cref="T:System.OperationCanceledException">
  5219. /// The query was canceled.
  5220. /// </exception>
  5221. public static TSource Last<TSource>(this ParallelQuery<TSource> source)
  5222. {
  5223. // @PERF: optimize for seekable data sources. E.g. if an array, we can
  5224. // seek directly to the last element.
  5225. if (source == null) throw new ArgumentNullException("source");
  5226. LastQueryOperator<TSource> queryOp = new LastQueryOperator<TSource>(source, null);
  5227. // If in conservative mode and a premature merge would be inserted by the First operator,
  5228. // run the whole query sequentially.
  5229. QuerySettings settings = queryOp.SpecifiedQuerySettings.WithDefaults();
  5230. if (queryOp.LimitsParallelism
  5231. && settings.ExecutionMode != ParallelExecutionMode.ForceParallelism)
  5232. {
  5233. IEnumerable<TSource> childAsSequential = queryOp.Child.AsSequentialQuery(settings.CancellationState.ExternalCancellationToken);
  5234. IEnumerable<TSource> childWithCancelChecks = CancellableEnumerable.Wrap(childAsSequential, settings.CancellationState.ExternalCancellationToken);
  5235. return ExceptionAggregator.WrapEnumerable(childWithCancelChecks, settings.CancellationState).Last();
  5236. }
  5237. return GetOneWithPossibleDefault(queryOp, false, false);
  5238. }
  5239. /// <summary>
  5240. /// Returns the last element of a parallel sequence that satisfies a specified condition.
  5241. /// </summary>
  5242. /// <typeparam name="TSource">The type of the elements of <paramref name="source"/>.</typeparam>
  5243. /// <param name="source">The sequence to return an element from.</param>
  5244. /// <param name="predicate">A function to test each element for a condition.</param>
  5245. /// <returns>
  5246. /// The last element in the sequence that passes the test in the specified predicate function.
  5247. /// </returns>
  5248. /// <exception cref="T:System.ArgumentNullException">
  5249. /// <paramref name="source"/> or <paramref name="predicate"/> is a null reference (Nothing in Visual Basic).
  5250. /// </exception>
  5251. /// <exception cref="T:System.InvalidOperationException">
  5252. /// No element in <paramref name="source"/> satisfies the condition in <paramref name="predicate"/>.
  5253. /// </exception>
  5254. /// <exception cref="T:System.AggregateException">
  5255. /// One or more exceptions occurred during the evaluation of the query.
  5256. /// </exception>
  5257. /// <exception cref="T:System.OperationCanceledException">
  5258. /// The query was canceled.
  5259. /// </exception>
  5260. public static TSource Last<TSource>(this ParallelQuery<TSource> source, Func<TSource, bool> predicate)
  5261. {
  5262. if (source == null) throw new ArgumentNullException("source");
  5263. if (predicate == null) throw new ArgumentNullException("predicate");
  5264. LastQueryOperator<TSource> queryOp = new LastQueryOperator<TSource>(source, predicate);
  5265. // If in conservative mode and a premature merge would be inserted by the First operator,
  5266. // run the whole query sequentially.
  5267. QuerySettings settings = queryOp.SpecifiedQuerySettings.WithDefaults();
  5268. if (queryOp.LimitsParallelism
  5269. && settings.ExecutionMode != ParallelExecutionMode.ForceParallelism)
  5270. {
  5271. IEnumerable<TSource> childAsSequential = queryOp.Child.AsSequentialQuery(settings.CancellationState.ExternalCancellationToken);
  5272. IEnumerable<TSource> childWithCancelChecks = CancellableEnumerable.Wrap(childAsSequential, settings.CancellationState.ExternalCancellationToken);
  5273. return ExceptionAggregator.WrapEnumerable(
  5274. childWithCancelChecks, settings.CancellationState)
  5275. .Last(ExceptionAggregator.WrapFunc<TSource, bool>(predicate, settings.CancellationState));
  5276. }
  5277. return GetOneWithPossibleDefault(queryOp, false, false);
  5278. }
  5279. /// <summary>
  5280. /// Returns the last element of a parallel sequence, or a default value if the
  5281. /// sequence contains no elements.
  5282. /// </summary>
  5283. /// <typeparam name="TSource">The type of the elements of <paramref name="source"/>.</typeparam>
  5284. /// <param name="source">The sequence to return an element from.</param>
  5285. /// <returns>
  5286. /// default(<typeparamref name="TSource"/>) if the source sequence is empty; otherwise, the last element in the sequence.
  5287. /// </returns>
  5288. /// <exception cref="T:System.ArgumentNullException">
  5289. /// <paramref name="source"/> is a null reference (Nothing in Visual Basic).
  5290. /// </exception>
  5291. /// <exception cref="T:System.AggregateException">
  5292. /// One or more exceptions occurred during the evaluation of the query.
  5293. /// </exception>
  5294. /// <exception cref="T:System.OperationCanceledException">
  5295. /// The query was canceled.
  5296. /// </exception>
  5297. public static TSource LastOrDefault<TSource>(this ParallelQuery<TSource> source)
  5298. {
  5299. // @PERF: optimize for seekable data sources. E.g. if an array, we can
  5300. // seek directly to the last element.
  5301. if (source == null) throw new ArgumentNullException("source");
  5302. LastQueryOperator<TSource> queryOp = new LastQueryOperator<TSource>(source, null);
  5303. // If in conservative mode and a premature merge would be inserted by the First operator,
  5304. // run the whole query sequentially.
  5305. QuerySettings settings = queryOp.SpecifiedQuerySettings.WithDefaults();
  5306. if (queryOp.LimitsParallelism
  5307. && settings.ExecutionMode != ParallelExecutionMode.ForceParallelism)
  5308. {
  5309. IEnumerable<TSource> childAsSequential = queryOp.Child.AsSequentialQuery(settings.CancellationState.ExternalCancellationToken);
  5310. IEnumerable<TSource> childWithCancelChecks = CancellableEnumerable.Wrap(childAsSequential, settings.CancellationState.ExternalCancellationToken);
  5311. return ExceptionAggregator.WrapEnumerable(childWithCancelChecks, settings.CancellationState).LastOrDefault();
  5312. }
  5313. return GetOneWithPossibleDefault(queryOp, false, true);
  5314. }
  5315. /// <summary>
  5316. /// Returns the last element of a parallel sequence that satisfies a condition, or
  5317. /// a default value if no such element is found.
  5318. /// </summary>
  5319. /// <typeparam name="TSource">The type of the elements of <paramref name="source"/>.</typeparam>
  5320. /// <param name="source">The sequence to return an element from.</param>
  5321. /// <param name="predicate">A function to test each element for a condition.</param>
  5322. /// <returns>
  5323. /// default(<typeparamref name="TSource"/>) if the sequence is empty or if no elements pass the test in the
  5324. /// predicate function; otherwise, the last element that passes the test in the predicate function.
  5325. /// </returns>
  5326. /// <exception cref="T:System.ArgumentNullException">
  5327. /// <paramref name="source"/> or <paramref name="predicate"/> is a null reference (Nothing in Visual Basic).
  5328. /// </exception>
  5329. /// <exception cref="T:System.AggregateException">
  5330. /// One or more exceptions occurred during the evaluation of the query.
  5331. /// </exception>
  5332. /// <exception cref="T:System.OperationCanceledException">
  5333. /// The query was canceled.
  5334. /// </exception>
  5335. public static TSource LastOrDefault<TSource>(this ParallelQuery<TSource> source, Func<TSource, bool> predicate)
  5336. {
  5337. if (source == null) throw new ArgumentNullException("source");
  5338. if (predicate == null) throw new ArgumentNullException("predicate");
  5339. LastQueryOperator<TSource> queryOp = new LastQueryOperator<TSource>(source, predicate);
  5340. // If in conservative mode and a premature merge would be inserted by the First operator,
  5341. // run the whole query sequentially.
  5342. QuerySettings settings = queryOp.SpecifiedQuerySettings.WithDefaults();
  5343. if (queryOp.LimitsParallelism
  5344. && settings.ExecutionMode != ParallelExecutionMode.ForceParallelism)
  5345. {
  5346. IEnumerable<TSource> childAsSequential = queryOp.Child.AsSequentialQuery(settings.CancellationState.ExternalCancellationToken);
  5347. IEnumerable<TSource> childWithCancelChecks = CancellableEnumerable.Wrap(childAsSequential, settings.CancellationState.ExternalCancellationToken);
  5348. return ExceptionAggregator.WrapEnumerable(
  5349. childWithCancelChecks, settings.CancellationState)
  5350. .LastOrDefault(ExceptionAggregator.WrapFunc<TSource, bool>(predicate, settings.CancellationState));
  5351. }
  5352. return GetOneWithPossibleDefault(queryOp, false, true);
  5353. }
  5354. //-----------------------------------------------------------------------------------
  5355. // Single yields the single element matching the optional predicate, or throws an
  5356. // exception if there is zero or more than one match. SingleOrDefault is similar
  5357. // except that it returns the default value in this condition.
  5358. //
  5359. /// <summary>
  5360. /// Returns the only element of a parallel sequence, and throws an exception if there is not
  5361. /// exactly one element in the sequence.
  5362. /// </summary>
  5363. /// <typeparam name="TSource">The type of the elements of <paramref name="source"/>.</typeparam>
  5364. /// <param name="source">The sequence to return the single element of.</param>
  5365. /// <returns>The single element of the input sequence.</returns>
  5366. /// <exception cref="T:System.ArgumentNullException">
  5367. /// <paramref name="source"/> is a null reference (Nothing in Visual Basic).
  5368. /// </exception>
  5369. /// <exception cref="T:System.InvalidOperationException">
  5370. /// The input sequence contains more than one element. -or- The input sequence is empty.
  5371. /// </exception>
  5372. /// <exception cref="T:System.AggregateException">
  5373. /// One or more exceptions occurred during the evaluation of the query.
  5374. /// </exception>
  5375. /// <exception cref="T:System.OperationCanceledException">
  5376. /// The query was canceled.
  5377. /// </exception>
  5378. public static TSource Single<TSource>(this ParallelQuery<TSource> source)
  5379. {
  5380. // @PERF: optimize for ICollection-typed data sources, i.e. we can just
  5381. // check the Count property and avoid costly fork/join/synchronization.
  5382. if (source == null) throw new ArgumentNullException("source");
  5383. return GetOneWithPossibleDefault(new SingleQueryOperator<TSource>(source, null), true, false);
  5384. }
  5385. /// <summary>
  5386. /// Returns the only element of a parallel sequence that satisfies a specified condition,
  5387. /// and throws an exception if more than one such element exists.
  5388. /// </summary>
  5389. /// <typeparam name="TSource">The type of the elements of <paramref name="source"/>.</typeparam>
  5390. /// <param name="source">The sequence to return the single element of.</param>
  5391. /// <param name="predicate">A function to test an element for a condition.</param>
  5392. /// <returns>The single element of the input sequence that satisfies a condition.</returns>
  5393. /// <exception cref="T:System.ArgumentNullException">
  5394. /// <paramref name="source"/> or <paramref name="predicate"/> is a null reference (Nothing in Visual Basic).
  5395. /// </exception>
  5396. /// <exception cref="T:System.InvalidOperationException">
  5397. /// No element satisfies the condition in <paramref name="predicate"/>. -or- More than one element satisfies the condition in <paramref name="predicate"/>.
  5398. /// </exception>
  5399. /// <exception cref="T:System.AggregateException">
  5400. /// One or more exceptions occurred during the evaluation of the query.
  5401. /// </exception>
  5402. /// <exception cref="T:System.OperationCanceledException">
  5403. /// The query was canceled.
  5404. /// </exception>
  5405. public static TSource Single<TSource>(this ParallelQuery<TSource> source, Func<TSource, bool> predicate)
  5406. {
  5407. if (source == null) throw new ArgumentNullException("source");
  5408. if (predicate == null) throw new ArgumentNullException("predicate");
  5409. return GetOneWithPossibleDefault(new SingleQueryOperator<TSource>(source, predicate), true, false);
  5410. }
  5411. /// <summary>
  5412. /// Returns the only element of a parallel sequence, or a default value if the sequence is
  5413. /// empty; this method throws an exception if there is more than one element in the sequence.
  5414. /// </summary>
  5415. /// <typeparam name="TSource">The type of the elements of <paramref name="source"/>.</typeparam>
  5416. /// <param name="source">The sequence to return the single element of.</param>
  5417. /// <returns>
  5418. /// The single element of the input sequence, or default(<typeparamref name="TSource"/>) if the
  5419. /// sequence contains no elements.
  5420. /// </returns>
  5421. /// <exception cref="T:System.ArgumentNullException">
  5422. /// <paramref name="source"/> is a null reference (Nothing in Visual Basic).
  5423. /// </exception>
  5424. /// <exception cref="T:System.AggregateException">
  5425. /// One or more exceptions occurred during the evaluation of the query.
  5426. /// </exception>
  5427. /// <exception cref="T:System.OperationCanceledException">
  5428. /// The query was canceled.
  5429. /// </exception>
  5430. public static TSource SingleOrDefault<TSource>(this ParallelQuery<TSource> source)
  5431. {
  5432. // @PERF: optimize for ICollection-typed data sources, i.e. we can just
  5433. // check the Count property and avoid costly fork/join/synchronization.
  5434. if (source == null) throw new ArgumentNullException("source");
  5435. return GetOneWithPossibleDefault(new SingleQueryOperator<TSource>(source, null), true, true);
  5436. }
  5437. /// <summary>
  5438. /// Returns the only element of a parallel sequence that satisfies a specified condition
  5439. /// or a default value if no such element exists; this method throws an exception
  5440. /// if more than one element satisfies the condition.
  5441. /// </summary>
  5442. /// <typeparam name="TSource">The type of the elements of <paramref name="source"/>.</typeparam>
  5443. /// <param name="source">The sequence to return the single element of.</param>
  5444. /// <param name="predicate">A function to test an element for a condition.</param>
  5445. /// <returns>
  5446. /// The single element of the input sequence that satisfies the condition, or
  5447. /// default(<typeparamref name="TSource"/>) if no such element is found.
  5448. /// </returns>
  5449. /// <exception cref="T:System.ArgumentNullException">
  5450. /// <paramref name="source"/> or <paramref name="predicate"/> is a null reference (Nothing in Visual Basic).
  5451. /// </exception>
  5452. /// <exception cref="T:System.AggregateException">
  5453. /// One or more exceptions occurred during the evaluation of the query.
  5454. /// </exception>
  5455. /// <exception cref="T:System.OperationCanceledException">
  5456. /// The query was canceled.
  5457. /// </exception>
  5458. public static TSource SingleOrDefault<TSource>(this ParallelQuery<TSource> source, Func<TSource, bool> predicate)
  5459. {
  5460. if (source == null) throw new ArgumentNullException("source");
  5461. if (predicate == null) throw new ArgumentNullException("predicate");
  5462. return GetOneWithPossibleDefault(new SingleQueryOperator<TSource>(source, predicate), true, true);
  5463. }
  5464. //-----------------------------------------------------------------------------------
  5465. // DefaultIfEmpty yields the data source, unmodified, if it is non-empty. Otherwise,
  5466. // it yields a single occurrence of the default value.
  5467. //
  5468. /// <summary>
  5469. /// Returns the elements of the specified parallel sequence or the type parameter's
  5470. /// default value in a singleton collection if the sequence is empty.
  5471. /// </summary>
  5472. /// <typeparam name="TSource">The type of the elements of <paramref name="source"/>.</typeparam>
  5473. /// <param name="source">The sequence to return a default value for if it is empty.</param>
  5474. /// <returns>
  5475. /// A sequence that contains default(<B>TSource</B>) if <paramref name="source"/> is empty; otherwise, <paramref name="source"/>.
  5476. /// </returns>
  5477. /// <exception cref="T:System.ArgumentNullException">
  5478. /// <paramref name="source"/> is a null reference (Nothing in Visual Basic).
  5479. /// </exception>
  5480. public static ParallelQuery<TSource> DefaultIfEmpty<TSource>(this ParallelQuery<TSource> source)
  5481. {
  5482. return DefaultIfEmpty<TSource>(source, default(TSource));
  5483. }
  5484. /// <summary>
  5485. /// Returns the elements of the specified parallel sequence or the specified value
  5486. /// in a singleton collection if the sequence is empty.
  5487. /// </summary>
  5488. /// <typeparam name="TSource">The type of the elements of <paramref name="source"/>.</typeparam>
  5489. /// <param name="source">The sequence to return the specified value for if it is empty.</param>
  5490. /// <param name="defaultValue">The value to return if the sequence is empty.</param>
  5491. /// <returns>
  5492. /// A sequence that contains <B>defaultValue</B> if <paramref name="source"/> is empty; otherwise, <paramref name="source"/>.
  5493. /// </returns>
  5494. /// <exception cref="T:System.ArgumentNullException">
  5495. /// <paramref name="source"/> is a null reference (Nothing in Visual Basic).
  5496. /// </exception>
  5497. public static ParallelQuery<TSource> DefaultIfEmpty<TSource>(this ParallelQuery<TSource> source, TSource defaultValue)
  5498. {
  5499. if (source == null) throw new ArgumentNullException("source");
  5500. return new DefaultIfEmptyQueryOperator<TSource>(source, defaultValue);
  5501. }
  5502. //-----------------------------------------------------------------------------------
  5503. // ElementAt yields an element at a specific index. If the data source doesn't
  5504. // contain such an element, an exception is thrown. Alternatively, ElementAtOrDefault
  5505. // will return a default value if the given index is invalid.
  5506. //
  5507. /// <summary>
  5508. /// Returns the element at a specified index in a parallel sequence.
  5509. /// </summary>
  5510. /// <typeparam name="TSource">The type of the elements of <paramref name="source"/>.</typeparam>
  5511. /// <param name="source">A sequence to return an element from.</param>
  5512. /// <param name="index">The zero-based index of the element to retrieve.</param>
  5513. /// <returns>The element at the specified position in the source sequence.</returns>
  5514. /// <exception cref="T:System.ArgumentNullException">
  5515. /// <paramref name="source"/> is a null reference (Nothing in Visual Basic).
  5516. /// </exception>
  5517. /// <exception cref="T:System.ArgumentOutOfRangeException">
  5518. /// <paramref name="index"/> is less than 0 or greater than or equal to the number of elements in <paramref name="source"/>.
  5519. /// </exception>
  5520. /// <exception cref="T:System.AggregateException">
  5521. /// One or more exceptions occurred during the evaluation of the query.
  5522. /// </exception>
  5523. /// <exception cref="T:System.OperationCanceledException">
  5524. /// The query was canceled.
  5525. /// </exception>
  5526. public static TSource ElementAt<TSource>(this ParallelQuery<TSource> source, int index)
  5527. {
  5528. if (source == null) throw new ArgumentNullException("source");
  5529. if (index < 0) throw new ArgumentOutOfRangeException("index");
  5530. // @PERF: there are obvious optimization opportunities for indexible data sources,
  5531. // since we can just seek to the element requested.
  5532. ElementAtQueryOperator<TSource> op = new ElementAtQueryOperator<TSource>(source, index);
  5533. TSource result;
  5534. if (op.Aggregate(out result, false))
  5535. {
  5536. return result;
  5537. }
  5538. throw new ArgumentOutOfRangeException("index");
  5539. }
  5540. /// <summary>
  5541. /// Returns the element at a specified index in a parallel sequence or a default value if the
  5542. /// index is out of range.
  5543. /// </summary>
  5544. /// <typeparam name="TSource">The type of the elements of <paramref name="source"/>.</typeparam>
  5545. /// <param name="source">A sequence to return an element from.</param>
  5546. /// <param name="index">The zero-based index of the element to retrieve.</param>
  5547. /// <returns>
  5548. /// default(<B>TSource</B>) if the index is outside the bounds of the source sequence;
  5549. /// otherwise, the element at the specified position in the source sequence.
  5550. /// </returns>
  5551. /// <exception cref="T:System.ArgumentNullException">
  5552. /// <paramref name="source"/> is a null reference (Nothing in Visual Basic).
  5553. /// </exception>
  5554. /// <exception cref="T:System.AggregateException">
  5555. /// One or more exceptions occurred during the evaluation of the query.
  5556. /// </exception>
  5557. /// <exception cref="T:System.OperationCanceledException">
  5558. /// The query was canceled.
  5559. /// </exception>
  5560. public static TSource ElementAtOrDefault<TSource>(this ParallelQuery<TSource> source, int index)
  5561. {
  5562. if (source == null) throw new ArgumentNullException("source");
  5563. // @PERF: there are obvious optimization opportunities for indexible data sources,
  5564. // since we can just seek to the element requested.
  5565. if (index >= 0)
  5566. {
  5567. ElementAtQueryOperator<TSource> op = new ElementAtQueryOperator<TSource>(source, index);
  5568. TSource result;
  5569. if (op.Aggregate(out result, true))
  5570. {
  5571. return result;
  5572. }
  5573. }
  5574. return default(TSource);
  5575. }
  5576. }
  5577. }