Stop Using FirstOrDefault in .NET! | Code Cop

Поділитися
Вставка
  • Опубліковано 18 вер 2024
  • Until the 30th of September get 30% off any course on Dometrain with code BTS30: dometrain.com/...
    Subscribe to my weekly newsletter: nickchapsas.com
    Become a Patreon and get special perks: / nickchapsas
    Hello, everybody. I'm Nick, and in this episode of Code Cop, I will explain why you should be using FirstOrDefault over Find in C# even though people on LinkedIn might tell you otherwise.
    Workshops: bit.ly/nickwor...
    Don't forget to comment, like and subscribe :)
    Social Media:
    Follow me on GitHub: github.com/Elf...
    Follow me on Twitter: / nickchapsas
    Connect on LinkedIn: / nick-chapsas
    Keep coding merch: keepcoding.shop
    #csharp #dotnet #codecop

КОМЕНТАРІ • 232

  • @mynameisshadywhat
    @mynameisshadywhat 2 дні тому +205

    Until I saw the Code Cop at the end of the title all my usages of FirstOrDefault flashed before my eyes

    • @alanschmitt9865
      @alanschmitt9865 2 дні тому +26

      Literally he drops these and I’m like “okay boys what are we refactoring today” 😂

    • @nkosinathimlotshwa3153
      @nkosinathimlotshwa3153 2 дні тому +1

      😂🤣😂🤣i stopped listening

    • @jonnybutcher3948
      @jonnybutcher3948 2 дні тому +2

      Exactly this, I hate the code cop vids.

    • @carlcruz2803
      @carlcruz2803 День тому

      😂

    • @TheOceanLoader
      @TheOceanLoader Годину тому

      They are the best way to learn things in a practical, real-world way

  • @hamzanasab1713
    @hamzanasab1713 2 дні тому +38

    Astronaut 1: Wait its a span?
    Astronaut 2: Always has been 'shoots gun'

  • @TanelTeede
    @TanelTeede 2 дні тому +168

    "it's spans. It's ALWAYS spans." -- Nick

    • @tedchirvasiu
      @tedchirvasiu 2 дні тому +75

      I wanna subscribe to Nick's OnlySpans

    • @shahzaibhassan2777
      @shahzaibhassan2777 2 дні тому +4

      This deserves an Oscar 🤣​@@tedchirvasiu

    • @silkfire
      @silkfire 2 дні тому

      Can someone care to explain?

    • @MichalMracka
      @MichalMracka 2 дні тому +2

      @@silkfire Maybe Indiana Jones? He did not like snake case as I remember...

    • @kotn3l
      @kotn3l 2 дні тому +1

      @@tedchirvasiu ohmygod LMAOO

  • @JP-hr3xq
    @JP-hr3xq 2 дні тому +133

    I hate LinkedIn. Everyone's out to prove how special they are. And it's never the smart ones doing it.

    • @fusedqyou
      @fusedqyou 2 дні тому +17

      Why? It is good advice, just outdated with the new .NET version.

    • @Natusch_
      @Natusch_ 2 дні тому +12

      The smart ones don't care much about how you do it as long as you're accomplishing real life solutions in a sufficient or, ideally, great way.

    • @tuckertcs
      @tuckertcs 2 дні тому +11

      @@fusedqyou The "smart" ones are out preaching incomplete advice while the actual smart ones are busy doing real-life work and accomplishing something.

    • @davidmartensson273
      @davidmartensson273 2 дні тому

      @@fusedqyou Even in the old version I would argue against it because find is more specialized. Sure it was faster, but for 99.9 % of use cases it will still be insignificant compared to even the fastest DB access the code does so if falls under premature optimization.
      Using FirstOrDefault means it will work for any enumerable so you can easily switch away from list if you need to and also change to singleordefault easily.
      And even IF you need the extra performance, depending on the use case find might not even be the best since you might have options to redesign the whole approach to get even more performance, and only after checking all that, falling back to an older more specific method should be used.
      At least in my opinion.
      Easy to read and maintain code is almost always the better code and old methods are often not as clear.
      FirstOrDefault is much more descriptive than Find since it includes how it handles not finding the value :)

    • @user-qf5mr7nl8d
      @user-qf5mr7nl8d 23 години тому +1

      ​@Natusch_ precisely. That's why my code reviews of others is usually passing quickly as long as there is something really bad, like never, and my code is always being dragged through idiotic nagging which have never resulted in any slightest improvements in any aspect so far. And yes, I have 30 years of uninterrupted experience while others have 8 tops. Your point explains it all.

  • @typinowly
    @typinowly 2 дні тому +95

    I am getting sick of this kind of "advice". I would always just use, what I find is the most readable/understandable (even if it is the supposed inferior performing version). And if I find my application to slow down or uselessly crank up in memory usage, I investigate and optimize the bottleneck. No point in optimizing, what doesn't need to be optimized.

    • @kimpedersen4746
      @kimpedersen4746 2 дні тому +5

      totally agree,. call it optimized for readabillity.

    • @mad_t
      @mad_t День тому +9

      Preemptive optimizing is pure evil.

    • @MaxQuagliotto
      @MaxQuagliotto День тому +2

      I agree with you. Plus -- the use-case for this is so simple and irrelevant... a better demonstration would be a list of a class type where the property of one of those classes matches.. with the caveat that the test data MUST have "duplicates" in there (or at least multiple records where the matching field has the same value -- and only return the FIRST of those...).

    • @brianviktor8212
      @brianviktor8212 11 годин тому

      In my domain of work performance has high priority. So whenever I can squeeze out a little more performance, why not. For example I created a lot of methods in my general use library that allow me to set byte values in byte arrays using unsafe. I do that quite a lot, both on client and server side (namely for TCP/UDP communication), and why do something worse if better is possible? I know it's more performant, and I know it's often used.
      Should I default to some "simple", inferior standard instead, because so far it wasn't a bottleneck yet? When I am working on something, I have to load the entire system into memory. That's the best time to work on it, and also to improve it. When I am done with it, I will forget too much of it, and it would take days or weeks to get into it.
      If I'd switch domains too much, I'd lose out more time on that (without benefit) than what optimizations take in time - especially if they are necessary/beneficial later anyway.

    • @typinowly
      @typinowly 10 годин тому

      ​@@brianviktor8212 Different projects have different performance requirements, but in my experience, premature optimization is often a curse. Why optimize for performance if it won’t significantly impact the app in the end? Especially if it comes at the cost of readability and maintainability. On top of that, you often need to make trade-offs between time and memory performance before you even know what kind of issue will cause a bottleneck.
      Of course, there are caveats. For example, I once worked on a originally statically rendered web-front-end where server-side queries to a specific data service were painfully slow, causing frequent timeouts. As a result, we implemented client-side caching and effectively built a modern JavaScript app for this one use case, allowing users to begin working while the data loaded. But months later, we finally reviewed the data server’s code and found the issue - a poorly scaling lookup-loop with multiple database queries inside each iteration. A single, somewhat ugly, database query fixed the issue.
      If the initial developer had been more performance-focused, this might have been avoided. However, management also could have listened when we identified the server as the bottleneck. Instead of a simple back-end fix, we spent months optimizing the front-end, which became unnecessary once the real issue was fixed.
      In the end, I prioritize readability. If a problem comes up, it's important that any competent team member - not just the original developer - can understand the code’s intent and fix the issue. Readability ensures that the team can adapt and optimize when it matters, using clear helper functions and selective comments to guide future changes (in general I dislike comments, but sometimes they are important). This way, the code may initially “perform worse”, but it’s maintainable by the whole team. At least that is the idea :D

  • @auronedgevicks7739
    @auronedgevicks7739 2 дні тому +34

    unless you're doing this a million times it's absurd to even think about any of this

    • @FlorianZevedei
      @FlorianZevedei День тому +2

      Period.

    • @vchap01
      @vchap01 День тому

      If you are searching for a value in the same list many times, creating a HashSet would be way more efficient at some memory expense.

  • @superpcstation
    @superpcstation 2 дні тому +26

    My jaw dropped when i saw the .net 9 results

  • @Meryovi
    @Meryovi 2 дні тому +11

    Analyzers suggesting the use of List (and Array) specific methods: Oh man, we screwed up.

    • @kevinlloyd9507
      @kevinlloyd9507 День тому +2

      I was about to say... I've had analyzers yelling at my for years to use Find on lists. In this guy's defense, it's been like this for years.

  • @antonmartyniuk
    @antonmartyniuk 2 дні тому +28

    Never use LINQ to filter data in the database, instead do all the filtering in memory 😅

    • @Anonymous-un2nj
      @Anonymous-un2nj 2 дні тому +1

      Huh why?

    • @antonmartyniuk
      @antonmartyniuk 2 дні тому +27

      @@Anonymous-un2nj it's a joke.
      An example of bad advice 😜

    • @NotACat20
      @NotACat20 2 дні тому +2

      It is joke and EF is not fastest nor best linq to database provider which additionally implements UoW - great old antipattern. More over linq is not best way to make a query. But if you can embed parameters in query (instead of using parameters) in some cases (semi dynamic queries mostly) - is requirement. Not sure if EF even can handle this.

    • @klocugh12
      @klocugh12 2 дні тому +1

      Nah, roll your own SQL to do it 😅

    • @NotACat20
      @NotACat20 2 дні тому

      @@klocugh12 just use linq2db - is much faster, is still linq and is done right.

  • @fusedqyou
    @fusedqyou 2 дні тому +52

    This is the first case where I see "bad/wrong advice" actually being very valid. It's just that the user used an older version of .NET for their example, but if it wasn't for the optimizations in the newer .NET version(s), then this advice should actually be used.

    • @christianhowell3140
      @christianhowell3140 2 дні тому +5

      If you never intend to update to newer .NET versions, sure. There are plenty of projects that will simply never migrate out of framework
      They probably SHOULD, buuuut yannow lol

    • @adambickford8720
      @adambickford8720 2 дні тому +11

      All advice would be good if it wasn't bad.
      The 'bad' advice is applying very specific performance advice as a general rule. If you know you have a very hot loop and need that performance, go down that road, but not otherwise. The more idiomatic the code, the more likely you'll benefit from general platform enhancements.

    • @Zikakoo
      @Zikakoo 2 дні тому +18

      I mean .NET 9 is not even released yet ... from my point of view that linkedin post is fine

    • @dennischeung6054
      @dennischeung6054 2 дні тому +11

      @@Zikakoo I think what Nick's point is not just .NET 9 is better, but to state that Microsoft will continuously improving Linq performance so just by staying in Linq, performance will be auto-upgraded in each patch. On the other hand, old method such as List.Find may not get improvement as much, as MS may try to replace them with Linq. So unless performance is critical and you are willing to manually modify the code every version update, using Linq may provide better cost-effectiveness in the long run

    • @fusedqyou
      @fusedqyou 2 дні тому +2

      @@dennischeung6054 Why would `Find` not receive the same treatment?

  • @testitestmann8819
    @testitestmann8819 2 дні тому +19

    Cries in Unity

    • @junior.santana
      @junior.santana 23 години тому

      Why? Doesn't Unity support Linq?

    • @testitestmann8819
      @testitestmann8819 16 годин тому +1

      @@junior.santana It does, but because Unity is reaaaally slow with updating to newer C# versions, Linq's performance is not that great and can be a real fps killer.

    • @junior.santana
      @junior.santana 10 годин тому

      @@testitestmann8819 I see. That's annoying, it's a use case that would benefit a lot from those micro-optimizations

  • @sasukesarutobi3862
    @sasukesarutobi3862 2 дні тому +7

    This is a great point that performance advice is so specific to versions and implementations. Forgetting this seems to be the cardinal sin of all these advice posts.

    • @NotACat20
      @NotACat20 2 дні тому

      It turns to idea what any perf-related decisions should be covered by perf-benchmarks, including benchmarking standard stuff (as base of decision). But this rarely matters.

  • @pratyushkumarsingh6161
    @pratyushkumarsingh6161 2 дні тому +1

    I had a hunch that Nick is going to create the video on this when I had first seen it on LinkedIn 😂 and here we are!!!

  • @arztje
    @arztje 2 дні тому +20

    I don't think comparing against a pre-release version of .Net is necessarily fair to disqualify the advice. It's good advice UNTIL .Net 9 comes out which makes this concern trivial.

    • @DEZK90
      @DEZK90 2 дні тому +5

      And maybe now someone goes in and optimizes the Fins method. Since they know what the backing array is it will be faster than the Linq method. So the whole point is once again valid and anything can be optimized by Microsoft at any time...

    • @YT-dr8qi
      @YT-dr8qi День тому +2

      I'd like to say it's a good advice until .NET 10 comes out as many projects migrate only to LTS versions.
      But, well, it's good only for hot parts of your code ehich greatly affect the performance (if any). Most of your code is not a hot path and don't bottleneck the performance

    • @Rizon1985
      @Rizon1985 День тому

      ​@@YT-dr8qi There are people who care about LTS? There is no practical difference between 18 or 36 months. Applications live 20 years or longer. And you're not going to get budget to upgrade applications without any practical improvement for business and especially not when you're using beta features like Blazor that still get big breaking changes every single new release.
      Choosing your .NET version is about which features you need. Through most of an applications' life, LTS/STS won't be a factor.

    • @zethoun
      @zethoun День тому

      @@Rizon1985 we have 3 internals apps, we upgrade them for every new LTS

  • @Mosern1977
    @Mosern1977 2 дні тому +6

    Number of times an in memory lookup has been the culprit of slowness in my professional life, is pretty darn few.
    Its always disk, network, database or some other external thingy.

    • @odomobo
      @odomobo 2 дні тому +2

      Or wrong algorithm!

    • @Mosern1977
      @Mosern1977 День тому +2

      @@odomobo - yes, some unintended nested loops is a fun one.

    • @nickbarton3191
      @nickbarton3191 17 годин тому

      True, the other big one in managed code in general is HEAP churn which I do optimise for. Otherwise, clean code all the way.

  • @231kickback
    @231kickback День тому +1

    It seems unlikely that a significant bottleneck in an application will come from using "FirstOrDefault" over "Find" for List. It's possible and for those of us that cannot upgrade our version of .NET due to external dependencies, that might be a reasonable optimization (assuming this is the problem). However, based on profiling we have done, our slowdowns are not this simple. Usually, issues are caused by repeated calls to our 3d party dependency for the same information over and over.
    TL;DR: Profile first, optimize later.

  • @inzyster
    @inzyster 2 дні тому +1

    🎵 span, span, span, span, lovely spaaaaaaan, lovelyyyy spaaaaaan 🎵

  • @peroyhav
    @peroyhav 2 дні тому +1

    Also, remember that Linq query extensions like FirstOrDefault and SingleOrDefault queries can be converted to SQL by Entity Framework, Collection specific methods might not have those optimizations, and might cause higher bandwidth between the application and database, same applies to Any vs Array,Exists etc. So always using collection specific methods is ill adviced by that alone.

  • @markiiitu
    @markiiitu 2 дні тому +1

    This also applies for Any/Exists: Exists was faster than Any, but in .NET 9, Any has been optimized to outperform Exists.

  • @diadetediotedio6918
    @diadetediotedio6918 2 дні тому +4

    This is one of those videos I quite don't like, not something like "you don't want to use the default implemented method of the type", it goes against what is designed in the language itself and feels like a very artificial advice.

  • @Juznik1389
    @Juznik1389 2 дні тому

    Love that you made a video about this. I was just on LinkedIn just this morning and saw this.

  • @mkwpaul
    @mkwpaul 2 дні тому +2

    I feel like the take away here is not that you use FirstOrDefault over Find because Microsoft is prioritizing it, but that contextless performance advice akin to "use this not this" should not be blindly followed without a deeper understanding and up-to-date knowledge.
    Over all I would even say that the original advice is not wrong. Its just gonna be out of date soon.

  • @martinprohn2433
    @martinprohn2433 2 дні тому +6

    At first I was a little confused, why FirstOrDefault is so much slower. That means that iterating over an enumerator is slower that iterating with indexer. Not sure why, the Enumerator of a list would surely do exactly the same. Where is the whole overhead coming from?
    But I also realized, that in majority of cases most of what is said here is actually not relevant. Because everytime I do `Select` and `Where` before calling `FirstOrDefault` non of that matters, because than `Find` is not available anyway and `FirstOrDefault` will use an Enumerator, even in .net 9.

    • @maschyt
      @maschyt 2 дні тому

      If you use a for loop and using an indexer, you are directly accessing the item’s memory position. If you use foreach/the enumerator for every item the enumerators MoveNext method needs to be called which also accesses the memory location and puts the value in the enumerator’s Current property. This is the overhead.

    • @narumikazuchi
      @narumikazuchi 2 дні тому +4

      I can actually answer that for you if you are still curious. The thing is, Linq operates on interfaces (until C# 9 where it also uses Spans apparently). Interfaces inherently are not concrete types and therefore have to do a lookup in the v-table (stores references to the actual method for overriding purposes) where to find the GetEnumerator() function to call. This is a small cost that you could neglect normally, the problem here lies in the fact that the GetEnumerator() returns another interface IEnumerator and when doing a foreach loop what happens under the hood is that there is first a call to GetEnumerator() and then basically a while loop "while(enumerator.MoveNext()) { T current = enumerator.Current; ...do stuff }" which is 2 lookups into the IEnumerator ' s v-table to find the function references. This is also why the difference in performance scales with the number of items in the IEnumerable and also why I always prefer to use concrete types instead of interfaces where possible.
      Hope this explains it good enough, I didn't want to write a whole essay, since this is not 100% the reason of whats happening but roughly what's most important.

    • @z0nx
      @z0nx 2 дні тому

      @@narumikazuchi So do you then also keep away from Select and Where, for the same reason? I mean that's where the magic happens most of the time.

    • @narumikazuchi
      @narumikazuchi 2 дні тому

      @@z0nx For my private projects, yes, but I also mainly use Spans there anyway and filter "by hand" if you will. For work projects, no, they are usually not as much of a performance lover as I am and writing a item.Where(...) is usually easier to decipher than what I do. I even got chewed out once for building an abstract syntax tree to create a dynamic predicate instead of just installing a nuget package and using the predicate builder from that package. So in short, I like doing things by hand, since I have the most control over what happens and not to say that I'm better than others, but I do think I know quite a bit about C# and performance, since I also know how alot of C# gets compiled down to IL code.
      And that is definitly not necessary for "normal" code.

    • @z0nx
      @z0nx 2 дні тому

      @@narumikazuchi Right, interesting. I personally don't get the obsession over getting into the nitty gritty like that, I'm much more into delivering code that shows intent. Wouldn't rust be more interesting at that point?

  • @renynzea
    @renynzea 2 дні тому +1

    My first thought would be "are you only searching for one thing, or multiple things"? More often then not it is multiple things, in the context of a loop (or several nested loops). At which point I would use HashSet, Dictionary, or a lookup table. I have lost count of the number of times I have seen other developers use Find (or First, or FirstOrDefault) for everything, no matter the context. Also, I almost never use a List directly these days. I might use ICollection, IReadOnlyList, or IEnumerable. Which might be backed by a list. Or it might not. So I rarely if ever optimize for a specific collection type, and when I do I'm usually back to using HashSet or Dictionary.

  • @vinny6935
    @vinny6935 День тому

    This was fantastic and honestly my mind was indeed blown with those results from .NET 9. Once I saw it was spans it made sense, I'm pretty excited to learn about what other optimizations were made in .NET 9 now. My question now is - what happens to programs that were compiled in .NET 8 but run in .NET 9? I assume they also get the optimizations because the methods in the runtime are what got optimized, but I don't know how much implementation is inlined into your program by the compiler vs. what is left as calls into the runtime.

  • @Thorarin
    @Thorarin 2 дні тому +2

    So basically Microsoft was lazy and didn't optimize Find 😉 I still don't think it's bad advise to use a specialized method over a LINQ method as it could be optimized further than the LINQ method. Probably not significantly in this case, but it's a good principle.

  • @EddieVillamor
    @EddieVillamor 2 дні тому

    I always had faith in linq optimization, glad they're pulling through! :)

  • @travisabrahamson8864
    @travisabrahamson8864 День тому

    I saw that advice and was still chewing on it, I'm glad you did this Nick. I was wondering if the LINQ optimizations were being considered.

  • @Jojor11
    @Jojor11 2 дні тому

    I generally take the approach of using linq until I have a good reason not to.
    I know a lot of optimizations are in place that may be better than mine, it gets updated and is very versatile. Plus I know it will work on any collection if it changes in the future.
    Once I have/need a specific behavior more attached to the specific collection or type, then I think about doing it differently

  • @sajadzargar.dev8
    @sajadzargar.dev8 День тому

    That was one hell of a thriller! I enjoyed it the way one would enjoy watching Hitchcock's movies.

  • @lacuevadelinsecto
    @lacuevadelinsecto День тому

    It may depend on the company, as not all companies are going to update their applications every time a new .NET version is released. Maybe if you are working on a project that can be upgraded frecuently, It can be a good advice, but if not, finding an optimal approach to that implemented version can be a better option.

  • @NickSteffen
    @NickSteffen 2 дні тому +2

    Find also happens to be a list only linq method. Many libraries only return ienumerables. If you have to convert an ienumerable to a list it’s going to to be slower than firstordefault.

    • @Rizon1985
      @Rizon1985 День тому

      Find isn't a linq method. It came along in 2.0 with List in System.Collections.Generic and uses a Predicate. They also created a Array.Find with a Predicate in 2.0 for all the boomers who didn't want to move on from arrays. LINQ (System.Linq) and lambda expressions (System.Linq.Expressions) were added in 3.5. and while thinking more globally about this whole concept, they moved on to using the Func/Action philosophy.
      But yeah for sakes of compatibility or refactoring it makes way more sense to work against IEnumerable than IList. There are concepts that become forgotten as more and more the .NET environment becomes littered by javascriptification of it's languages and specifically aiming at C# as a victim.

    • @Rizon1985
      @Rizon1985 День тому +1

      ​@@krs-tube The person I replied to said "a list only linq method" so I explained it's not a linq method.
      So take your own advice and get some social lessons while you're at it.

    • @krs-tube
      @krs-tube День тому

      @@Rizon1985 I tagged the wrong person in my reply, appologies fam!

    • @krs-tube
      @krs-tube День тому

      Nick specifically said and shown that .Find is a method on List() I guess you watched carefuly before dropping your hot take

    • @NickSteffen
      @NickSteffen День тому

      @@krs-tube He said it but never fully explained why it was bad and what the consequences were…. I guess you just like posting mean comments for a dopamine hit…. Thanks for your useful comment

  • @emanuelrodriguez3155
    @emanuelrodriguez3155 2 дні тому

    Great video! I would like to see how this method behaive with EF

  • @minnesotasteve
    @minnesotasteve 2 дні тому +11

    Premature optimization. There’s usually something else your doing that results in multi second responses you should fix before going down this rabbit hole.

    • @diadetediotedio6918
      @diadetediotedio6918 2 дні тому +1

      What rabbit hole, lol? This is a bizarre take for something that is neither absurd not problematic, it is an almost free thing you could do. And while I agree that your project to this exclusively because of optimization factors is a premature optimization, doing this from start will not be a problem.

    • @fionnlanghans
      @fionnlanghans 2 дні тому

      No, that's bad code

    • @minnesotasteve
      @minnesotasteve 2 дні тому

      @@diadetediotedio6918 It's more important to have readable code than chase micro-optimization.

  • @PajakTheBlind
    @PajakTheBlind 2 дні тому +2

    Another example of being too smart for your own good. Or rather generalizing over a broader topic based on specific example.
    Your method runs slow? Profile it and find the lowest hanging fruit. Cautiously build a heuristic over it, but only to potentially detect similar issues in the future and not to dismiss one type/method over another.

    • @NotACat20
      @NotACat20 2 дні тому

      You cant profile method which did not run in loop. It might be called few times per seconds, but it still adds dead weight. Performance starts from doing things efficiently in minimal way. Optimizing via profiling - is cheaper way to make "slow" things bit faster. Also any benchmark (micro or profiler) can't show scalability. So all this standard stuff like pick profiler and go is rubbish.

    • @diadetediotedio6918
      @diadetediotedio6918 2 дні тому +1

      ​@@NotACat20
      The idea of using a profiler is to lower the bar of things that are responsible for the major slowdowns in your application, so it is pretty profilable, yes, it is not rubbish.

    • @NotACat20
      @NotACat20 2 дні тому

      @@diadetediotedio6918 you will not able profile inefficiency between methods shown in this video.

  • @mrwensveen
    @mrwensveen День тому +2

    Crazy that TryGetFirst doesn't return a boolean but the found element, and sets the bool found as the out parameter. Maybe it's a memory allocation optimization or something but it looks weird.

  • @DjimmyTrovy
    @DjimmyTrovy 2 дні тому +16

    Very insightful analysis but I have to disagree somewhat on not using something that currently performs better because Microsoft will eventually optimize it.

    • @okmarshall
      @okmarshall 2 дні тому

      It's highly situational. And picking the right method is what separates good engineers for mediocre. If you really, really need that performance right now, then use Find. If you don't care all that much and don't want to refactor code, then use Linq everywhere and play the odds that it'll get faster and faster over time.

    • @shahzaibhassan2777
      @shahzaibhassan2777 2 дні тому +1

      You are somewhat right. It all depends on the situation. If you think you can upgrade the code later with latest version, then it's fine. But most of the times i would go for something more general/generic. I'll just have to increase the version & i get the benefits.

    • @DjimmyTrovy
      @DjimmyTrovy 2 дні тому

      @@shahzaibhassan2777 Yep

    • @simonwood2448
      @simonwood2448 2 дні тому

      I would rely on solar analysers to remove the cognitive load

  • @alexclark6777
    @alexclark6777 День тому

    Is Predicate considered old-hat now? I thought it was basically just a shorthand way of saying Func ?

  • @vyteniskajackas7579
    @vyteniskajackas7579 2 дні тому

    Saw this post on LinkedIn today😅

  • @krss6256
    @krss6256 2 дні тому

    That is a decent improvement in performance for free!

  • @Matt23488
    @Matt23488 2 дні тому +1

    Why would you prefer `Func` over `Predicate`? The latter is more descriptive. What makes it "not modern"? Seems arbitrary to me.

    • @artemisDev
      @artemisDev 2 дні тому

      Func is definitely more descriptive, since you can see it returns a bool without knowing what a predicate means. Also Func can have more than one (16 in fact) input types.
      Predicate is just a very specific implementation, feels redundant.

    • @DEZK90
      @DEZK90 2 дні тому

      ​@@artemisDev yes thats what the name predicate implies. We have one condition and it can be either true or false.
      So when you read predicate somewhere normally you should know that you can pass down some expression that should return either true or false.

    • @David-id6jw
      @David-id6jw 2 дні тому

      A Predicate is just one very specific version of Func. Meanwhile, the Func can be Func, Func, Func, etc. They realized that the Func (or Action) generics covered everything, and that the specialized versions like Predicate were just kind of confusing and slightly non-compatible.
      There's no functional difference in behavior between a Func and a Predicate, but you can't substitute one for the other because they are different types (although a lambda can be converted to either). I believe only the Array and List classes use Predicate, while LINQ always uses Func. Since LINQ is preferred for almost everything, and LINQ tries to have a unified syntax, encountering a specialized form of Func just introduces a confusion that doesn't need to be there.
      "Predicate" is definitely more descriptive (for me; I don't know about everyone else), but it introduces the concept of specialized terms that act as 'exceptions' to the general Func rule, and that's just a conceptual 'leak' that you're better off not surfacing in the language syntax.
      And it's "not modern" because Predicate was introduced way early, before MS realized it was a bad idea. Unfortunately, by then they couldn't get rid of it, so now it's mostly just, "Please ignore this little bit of legacy trivia", or "Use LINQ instead."

    • @Matt23488
      @Matt23488 2 дні тому

      @@artemisDev a predicate IS a condition that should evaluate to `true` when applied to something. The name `Predicate` carries semantic meaning that `Func` does not.

  • @barybatle
    @barybatle 2 дні тому

    thank you for this series, I learn a lot

  • @TheOceanLoader
    @TheOceanLoader 3 години тому

    Code Cop?! Issue arrest warrants for some of the guys on my dev team please! They are bad offenders!

  • @ChristianHowell
    @ChristianHowell День тому

    OK, I made my comments because I'm always calling a DB with LINQ... With memory collections, I'm usually on the client... I guess I can use it with Blazor though... There are a lot of cases where you want to keep data local rather than call the DB for lookups...

  • @funkwurm
    @funkwurm День тому

    I’m using the Array specific Find and Exists methods as SonarQube advised me to do. We’re on .Net 8 right now, maybe I should run some benchmarks.

  • @MKarl4
    @MKarl4 2 дні тому

    Stephen Toub is doing his magic 😂

  • @margosdesarian
    @margosdesarian 2 дні тому

    Wow - you are blowing my mind

  • @ferzik1508
    @ferzik1508 2 дні тому

    You speak as fast as your code runs in dotnet 9, however I prefer find method talk speed😂

  • @marceloleoncaceres6826
    @marceloleoncaceres6826 18 годин тому

    Thanks for the explanation,

  • @FlorianZevedei
    @FlorianZevedei День тому +1

    Haha I had seen this one 2 or 3 days ago on LinkedIn xD

  • @zheniachubarov3384
    @zheniachubarov3384 День тому

    Could you make a video about spans and why they are so cool?

  • @crahun
    @crahun День тому

    Really nice advice!

  • @frankroos1167
    @frankroos1167 День тому

    I am a little curious about the performance on "not found". These tend to have very different characteristics.
    Other than that, just this week, I have been looking at replacing FirstOrDefault with Find on a .NET 8 project. Looks like it is good...until we switch to 9 (or probably 10)

  • @andreyz3133
    @andreyz3133 День тому

    Imagine you can create bad posts on LinkedIn just to be a star of the next video from Nick Badass

  • @MaiconLLoti
    @MaiconLLoti 2 дні тому +2

    I still don't understand how Find can be faster in .NET 8 if the methods basically do the same thing... is it something in the IL?

    • @nickchapsas
      @nickchapsas  2 дні тому +16

      It’s the enumerator

    • @hkrickybjj
      @hkrickybjj 2 дні тому

      find is specialized for list, allowing faster access

    • @asdfxyz_randomname2133
      @asdfxyz_randomname2133 2 дні тому

      Theoretically, just looking at the name, find wouldn't neccessarily need to iterate in order, so if you had list.FirstOrDefault(x => x.Firstname == "John") and list.Find(x => x.Firstname == "John"), it could get you a different object.
      But in this case, Find iterates in order and the difference is just enumerator overhead.

  • @Thompsoncs
    @Thompsoncs 2 дні тому

    Another reason why you shouldn't write custom code to replace readable and consise linq unless you absolutely have to for performance reasons. Your custom approach is unlikely to get optimized by using a new version, whereas builtin code might.

  • @sleeper-cassie
    @sleeper-cassie 2 дні тому

    I try to avoid SingleOrDefault, but that's just because of the cost of throwing an exception.

  • @jacobhuebert8298
    @jacobhuebert8298 2 дні тому +4

    And why exactly is advising people on how to use LINQ properly in the current LTS considered bad advice simply because a prerelease of an STS changes performance?
    Yes, the benchmarks didn't match the sample code in the image. Yes that is misleading. Yes value and reference types behave differently. But the advice was sound in the current LTS.
    Taking someone's advice and saying it is bad simply because it changes in a prerelease of an STS is silly

    • @brianwestfall8105
      @brianwestfall8105 2 дні тому +2

      I agree with you completely. This video seems to be in bad taste.

  • @HiImKyle
    @HiImKyle День тому

    Sure, it might be slower, but I'll still use FirstOrDefault over Find.

  • @ethanr0x
    @ethanr0x День тому +1

    Why is span iteration faster than array iteration!?

  • @_grigoryta
    @_grigoryta 2 дні тому +1

    Meh. Microsoft can optimize LINQ all they want. Won't do you any good if your projects are .NET Core 3.1 in production and no one is planning to change that

  • @lukegordon4734
    @lukegordon4734 День тому

    At 4:06 I thought it might've been a local issue where Rider no longer jumps to the appropriate definition now on the first attempt. It loads the source files and then you have to go back and re-jump. I hope they fix that soon b/c I swear it used to work

  • @gosich
    @gosich 2 дні тому

    SingleOrDefault doesn't go through a collection twice the length. It finds first match and continues to look for one more match, which in worst case leads to the end of the collection, and that's it.

    • @nickchapsas
      @nickchapsas  День тому +2

      And if the first match is in the middle of the collection and there isn’t a second match, the it goes twice the length, which is what I said in the video

    • @gosich
      @gosich День тому

      @@nickchapsas ah, then I misunderstood you, sorry!

  • @FatbocSlin
    @FatbocSlin День тому

    Can you update the test to have a sealed IntWrapper and test & compare it across 8 & 9?
    Optimally have a test with the latest Framework version for library maintainers
    Maybe just make it a UA-cam Short, if it isn't enough content

  • @SG97
    @SG97 2 дні тому

    We've taken SonarLint for our legacy .net fx monolith as a linter to fix obvious "problems" in our codebase as we go. Have you experimented with linters and if so, idea for a video?

  • @harisimer
    @harisimer 2 дні тому

    you use FirstOrDefault because the name is more precise, that how you can also tell that find is an old version.
    And if you dont care about this, you always build the loop yourself, because LINQ was garbage performance since release.
    good to see thats getting better.

  • @regestea
    @regestea 2 дні тому

    I cannot find any Blazor Deep Dive course. Is it currently being recorded?

    • @nickchapsas
      @nickchapsas  2 дні тому +2

      Yes, Jimmy is currently working on it

  • @phantomofthelpac
    @phantomofthelpac 2 дні тому

    I find your title confusing. I admit I'm not a very regular viewer, but I read the title initially as what your final advice is, not the original claim that you're going to dispute as the Code Cop. If you'd put "Stop Using FirstOrDefault" in quotes followed by code cop, that would make it clearer, imo, that someone else said to stop and you don't agree.

  • @jonathanschafer4111
    @jonathanschafer4111 2 дні тому

    Seems like MS wouldn't have to rewrite Find to use Spans so much as just point Find to the whatever method the FirstOrDefault is using and then maybe handle the result differently? I didn't look too closely at the code

  • @Zanin001
    @Zanin001 2 дні тому

    Im working with a company that takes a long time to update dotnet, is it not worth making this chantge, since we are stil on dotnet 7? Performance is important for our software

  • @artemz9054
    @artemz9054 2 дні тому

    Мое почтение Нику и ребятам из Майкрософт.

  • @keyser456
    @keyser456 2 дні тому +4

    "Microsoft will optimize LINQ in every release because they know how much it is used" -- Yet it took them until v9 of Core (setting aside all the years of full Framework) to optimize this?

    • @BenMcCallums
      @BenMcCallums 2 дні тому +4

      Span was only introduced in 2017. It takes time for folks to discover where it can be utilised, and I'm sure they're getting better at that as time goes on.

    • @keyser456
      @keyser456 2 дні тому

      @@BenMcCallums Oh, so _only_ 6 or 7 major releases ago? :)

    • @protox4
      @protox4 2 дні тому

      I mean, they're special-casing arrays and lists here. Other types won't receive that same optimization (including chained Linq queries).

  • @billy65bob
    @billy65bob 2 дні тому +1

    Dayum... why is the wrapped version so much worse in .NET 8?
    Something bizarre is going on there...

    • @artemisDev
      @artemisDev 2 дні тому

      Cost of de-referencing, memory lookups, cache fails perhaps?

    • @billy65bob
      @billy65bob 2 дні тому +1

      @@artemisDev those factors should be fairly equivalent, since they're executing identical predicates in an identical manner to find a match.
      Only difference is the Enumerator, so I'd personally expect the same performance delta between ref types as there was between value types...

  • @mikebarber1
    @mikebarber1 День тому

    Dangit, Sonarqube is flagged all of my FirstOrDefaults in my projects and telling me to replace them with Find..... And I've made the change to make it quit nagging me...

  • @NotACat20
    @NotACat20 2 дні тому

    One of thing which uncovered is what arrays are covariant and always pays for this. One of way to get rid about this - is make array of struct wrapper of class T. This is standard practice for any library, including dotnet itself. I'm doest say what results fully dependent on this, but it may add own overhead in given microbenchmarks.
    PS: It is actually good finding, i guess Find method may be improved in same way. Report issue on dotnet/runtime? :)

  • @diegolobo7952
    @diegolobo7952 День тому

    Great!

  • @ThugLifeModafocah
    @ThugLifeModafocah 2 дні тому

    so, it depends on which .net version you are. 8 and below, find is better. Way better. After 9, then firstOrDefault is the way.

  • @maali82
    @maali82 2 дні тому

    yes, very clickbaity considering how many FirstOrDefaults I have in database queries :)

  • @ChristianHowell
    @ChristianHowell День тому

    I'm hoping this is a what not to do... You use FirstOrDefaultAsync so you will return null...

  • @troncek
    @troncek 2 дні тому

    Neat.

  • @liamhotspur9182
    @liamhotspur9182 6 годин тому

    code cop, funny!

  •  2 дні тому +1

    OnlySpans 😂

  • @ChrisOfSDUB
    @ChrisOfSDUB 16 годин тому

    Writing about LINQ on LinkedIn???

  • @leftjabrighthook
    @leftjabrighthook День тому

    Unless your app is making millions ($) per hour, this is so pointless.... honestly dont have to time to worry about nanoseconds in my code that get's hit maybe a thousand times a day.

  • @adek86
    @adek86 2 дні тому

    Your code is nothing like the one from LinkeIn's picture. Original code was checking if x == 4 and not x==3 like in your example :)

  • @ItsYozza
    @ItsYozza День тому

    Who is going to code cop this video? The conclusion of the video is based on changing the project framework to a version that isn't officially released yet. This advice is probably not practical for majority of large scale applications as it's not feasible for them to switch to an RC version of .NET at the drop of a hat. Not to mention that there will be tonnes of large enterprise applications that still run on .NET framework. The original post is right for majority of situations, whereas your advice is only valid for .NET 9?

    • @nickchapsas
      @nickchapsas  23 години тому

      Are you stuck in .NET Framework?

  • @hanneshold9675
    @hanneshold9675 2 дні тому

    Good sample, but the title is kind of misleading 🤔

  • @abhigupta3193
    @abhigupta3193 9 годин тому

    Hashtable

  • @suhwahong
    @suhwahong 2 дні тому

    네이티브 코드를 짜는게 최선이라고 하던가.. c언어가 cpp보다 빠르니 c를 사용해야해 라는 구시대적 개발론 .. 그냥 어셈블리로 짜는게 가장 즇은 해안이네.. 어셈블리야 말로 개떡같은 코드 짜기 딱좋지...

  • @matsnilsson3412
    @matsnilsson3412 День тому

    With respect, please add "questionable advice" or similar in the title for this kind of clip.

  • @Larsan
    @Larsan День тому

    Mind = Blown :O

  • @therobertbishop
    @therobertbishop День тому

    8O

  • @ronaldoperes1202
    @ronaldoperes1202 День тому

    Stop using hints from strange people from internet..... lol

  • @mirmostafa
    @mirmostafa 2 дні тому

    😲😲🤯🤯

  • @fusedqyou
    @fusedqyou 2 дні тому +3

    4:17 I don't see why `Predicate` would not be used anymore when it's clearer than a general `Func`?

    • @nickchapsas
      @nickchapsas  2 дні тому +4

      Is it?

    • @fusedqyou
      @fusedqyou 2 дні тому +2

      @@nickchapsas Sure, same reason why you'd write a delegate type rather than use a raw Func/Action in parameters or variables, because it improves readability. In this case it's already done for you.

    • @alanschmitt9865
      @alanschmitt9865 2 дні тому +1

      @@fusedqyouUnfortunately readability isn’t objective. Look at Ruby.

    • @fusedqyou
      @fusedqyou 2 дні тому

      @@alanschmitt9865 Wasn't my point, though? Why would it not be used anymore regardless?

    • @alanschmitt9865
      @alanschmitt9865 2 дні тому

      @@fusedqyou Because someone on the .NET team disagrees with you on readability I suppose.

  • @mariocamspam72
    @mariocamspam72 2 дні тому +1

    You'd do great in politics :P

  • @fgsdhdfgjfyhsg
    @fgsdhdfgjfyhsg 2 дні тому

    these people should be named and shamed tbh

    •  2 дні тому +3

      Interesting how that comment actually has the exact same problem as these posts "these people should be named and shamed"... same as "Don't do A, do B instead"... In this case it's also that bad of advice either... If .Net 9 (that is unreleased and still might still change) did not have optimizations, this video would probably not exist.
      The problem is not the posts themself, the problem is usually the lack of context they got on LinkedIn. But I think any developer with her/his own opinion has said "Do A instead of B" at some point, at least I have done it, and Nick has several videos where he could Code Cop his younger (and current) self.
      Shaming is not the way of going, and especially not after a monologue with no more context than on LinkedIn to begin with. All added context here is then taken out of context of the original post. So only way a name dropping could be justified, is if this was a dialog between Nick and the original author of the post, and the author was OK with it.

    • @Assgier
      @Assgier 2 дні тому

      I think mr. fgsdhdfgjfyhsg does have a point. It would at least scare off them career tigers a bit if they suddenly risk being unmasked in public.

  • @mansoursepehrjoo7568
    @mansoursepehrjoo7568 2 дні тому

    Great ❤

  • @EnissonBruno
    @EnissonBruno 2 дні тому

    Me using both Find and FirstOrDefault... in .net 7 😱