The fastest way to cast objects in C# is not so obvious

Sdílet
Vložit
  • čas přidán 28. 08. 2022
  • Check out my courses: dometrain.com
    Become a Patreon and get source code access: / nickchapsas
    Hello everybody I'm Nick and in this video I will show you all the main ways you can cast an object in C# and take a closer look at how the fastest way to cast objects when working on enumerables is probably not what you think it is.
    Don't forget to comment, like and subscribe :)
    Social Media:
    Follow me on GitHub: bit.ly/ChapsasGitHub
    Follow me on Twitter: bit.ly/ChapsasTwitter
    Connect on LinkedIn: bit.ly/ChapsasLinkedIn
    Keep coding merch: keepcoding.shop
    #csharp #dotnet

Komentáře • 146

  • @MagicNumberArg
    @MagicNumberArg Před rokem +214

    B.GetType() == typeof(A) will fail when inheritance is in play. B is A will still work.

    • @nickchapsas
      @nickchapsas  Před rokem +108

      That is correct, I should have mentioned the behavioural difference in the video

    • @Krilllind
      @Krilllind Před rokem +15

      Very true, but for most modern development I would suggest using composition over inheritance and then this won't be an issue 😊

    • @fkeyzuwu
      @fkeyzuwu Před rokem

      really? i did this a few days ago and didnt have problems..

    • @realtimberstalker
      @realtimberstalker Před rokem +8

      In this instance you could use the IsSubclassOf or IsAssaignableTo methods.

    • @IceQub3
      @IceQub3 Před rokem +4

      @@Krilllind if you want to check for interface implementations you need this, or an example you want to check if an object implements IDisposable, using the class object reference wont work, an you will need somthing else.

  • @cala-br
    @cala-br Před rokem +124

    To add to the Match Casting, if you invert the condition you can use the casted variable outside of the if scope.
    That is
    if (StaticObjects.Nick is not Person nick)
    return;
    Console.WriteLine(nick.FullName);

    • @guiorgy
      @guiorgy Před rokem +7

      Wow, that's good to know. TY

    • @jonathandunn9302
      @jonathandunn9302 Před rokem +3

      Took me a while to get used to this syntax but it's really useful in some instances!

    • @cala-br
      @cala-br Před rokem +1

      ​@@jonathandunn9302 Yup, it really comes in handy

    • @cala-br
      @cala-br Před rokem

      @@guiorgy You're welcome!

    • @evancombs5159
      @evancombs5159 Před rokem

      Please don't do this, it reduces code clarity.

  • @masonwheeler6536
    @masonwheeler6536 Před rokem +1

    I'm not surprised to see that the typeof comparison is the fastest. This is exactly what I'd expect, because it's checking an exact type match, one value against one value, rather than a type hierarchy match of a chain of values against one value. (And even when it only checks the first value in the chain, it's still using code that's meant to traverse the entire chain, so you 'd expect there to be some overhead there.)
    The tradeoff here is that there's no polymorphism. It will match objects of type Person, but not objects of types that inherit from Person, where the *is* keyword and any of the casts mentioned in this video will match subclasses as well.

  • @alexclark6777
    @alexclark6777 Před rokem +45

    Would be interesting to see this in SharpLab to see if the lowered code is different. I would assume that the comparison of b.GetType() to typeof(A) is fastest because it's doing an exact comparison, whereas B is A is checking to see if B is the same OR a descended type of A.
    Properly interesting test - this is the kind of C# trivia that I love, and keeps me coming back to your channel.

    • @ricardopieper11
      @ricardopieper11 Před rokem +3

      Indeed B is A checks for subtypes, while GetType() == typeof(A) should be just a pointer equality check, or whatever ReferenceEquals does. .GetType() should be very very fast because it always returns the same type instance/same ptr.

  • @ziaulhasanhamim3931
    @ziaulhasanhamim3931 Před rokem +21

    What about this?
    People.Select(x => x as Person)
    .Where(x => x is not null)
    .ToList()
    I think this will be the fastest because the all the others essentially cast the object twice. In hard cast also you first safe cast then again you hard cast

    • @wesplybon9510
      @wesplybon9510 Před rokem +10

      Benchmarked that for ya:
      | Method | Mean | Error | StdDev | Allocated |
      |--------------------- |----------:|----------:|----------:|----------:|
      | NicksFastest | 6.346 us | 0.1020 us | 0.0904 us | 16.36 KB |
      | InternetGuysQuestion | 15.097 us | 0.1417 us | 0.1325 us | 16.34 KB |
      As you can see Nick's suggestion still comes out over twice as fast. That's because hard casting is still faster than "as" or "is" casting. The type check in the fastest method is non-impactful to speed because nothing additional needs to happen to check the type except comparing some metadata already on hand. The type check is only 3 times slower than performing a comparison against an integer! That overhead is barely worth worrying about when used with any form of casting. However, your observations are right, the other methods are awful because they both have to actually perform a cast during the type check, and then a cast afterward. On top of the type check and hard casting being very fast, that's also why Nick's method is so much faster.
      [Later Edit] actually the overhead of the type check in the fastest method IS worth worrying about, but it won't get much faster. It takes up about a quarter of the overall execution time, which makes sense when comparing with Nick's results on hard casting. Any difference there is probably handling of the enumeration. If you don't need the safety checks or the flexibility of checking base types, I'd say it's well worth using, particularly in list casts.

    • @ziaulhasanhamim3931
      @ziaulhasanhamim3931 Před rokem +2

      @@wesplybon9510 yes you are right. Here the performance were not so obvious why it was happening like the OfType was so slow. My way also very slow. The performance difference here is for linq not for casting. My biggest problem with linq is it's not consistent with it's performance. Like in linq some methods are very optimized for array and list type collections. Like where and select. But OfType doesn't optimize anything for array or list. If you fist select then do where it also don't optimize that path. So if you want to get the actual result you need to use a custom IEnumerable which isn't optimized in any linq method

  • @ToadieBog
    @ToadieBog Před rokem +7

    Nick, seems like I always learn something new with your videos. Thank you so much for your content and your contribution to the community. Great stuff!

  • @brianm1864
    @brianm1864 Před rokem +15

    Probably the most important thing I've learned from your videos... I benchmark things all the time to see what performs best. Thanks for the great videos!

    • @MechMK1
      @MechMK1 Před rokem

      Benchmark what matters. I assure you, your casts don't. Whenever you have poor performance, it's down to one of these things:
      - Wrong algorithm
      - Repeated work
      - Poor IO
      - Waiting for mutexes
      I have never EVER been in a situation, where I said "Man, if only my casts were half a nanosecond faster".

    • @brianm1864
      @brianm1864 Před rokem +2

      @@MechMK1 I wasn't actually referring to casts, but it's always good to know the most efficient ways to do anything, even if you aren't going to use the most efficient. But I've used benchmark for many things, including comparing algorithms, testing the performance of 3rd party libraries and database queries.

    • @boxacuva
      @boxacuva Před rokem

      @@MechMK1 I think he confused Benchmark with analysing code.

  • @HeinzSeinz
    @HeinzSeinz Před rokem +9

    Fun fact: even if the as-cast returned null, Chuck Norris is able to read this null reference!

  • @dimensionaltrader
    @dimensionaltrader Před rokem

    Exceptionally clear & helpful. Great stuff.

  • @kevonboxill9455
    @kevonboxill9455 Před 3 měsíci

    great great video! This is my 6th video searching for a good explanation on object type casting ,even tho it was about performance!!

  • @wesplybon9510
    @wesplybon9510 Před rokem

    I'm not surprised by these results. The rest of those have to either first perform a cast to check the type (as operator), or compare type COMPATABILITY (is operator). But the fastest solution makes sense as it just gets the current type, checks it against a single type and then hard casts it. Thanks Nick, this was instructive and insightful as always!

  • @Z3rgatul
    @Z3rgatul Před rokem +5

    LOL, why everyone is thinking GetType() is the slowest?
    GetType() just returns pointer to Type object. This object is already in the memory, nothing is getting allocated. No conditional statements inside. Just look at the object header and get pointer here.
    And comparing 2 Type objects is just comparing 2 pointers.

    • @nickchapsas
      @nickchapsas  Před rokem +6

      Because most people associate GetType with reflection and to be fair, before the GetTypeInfo method was added, get type was heavier.

  • @xavhow
    @xavhow Před rokem

    Great vid, that's why I avoid object and type casting as much as possible... especially when dealing with large dataset!
    One question, in your example, isn't generic is better way of handling it in the context of enumerable... unless you really have to mix data types in one dataset (which is bad in my view). I know you are trying to compare casting speed.

  • @nooftube2541
    @nooftube2541 Před rokem

    you also can specify type in ToList() call instead of excplicit cast before calling ToList :)

  • @GregUzelac
    @GregUzelac Před rokem

    I too was surprised. Wow. Thank you.

  • @kirillhorn3186
    @kirillhorn3186 Před rokem

    Thank you very much for your videos! I have learnt a lot!!!

  • @haxi52
    @haxi52 Před rokem +3

    Thank you for your last comment about micro-optimizations. The cost of the next dev reading your code FAR outweighs the cost of writing ugly but "fast" code.

  • @stacklysm
    @stacklysm Před rokem

    The lesson I got from the video is: If possible, don't use the object type, this avoids unnecessary casts, nulls and overall headaches.
    Great video as always

  • @alphaanar2651
    @alphaanar2651 Před rokem +28

    I use Unsafe.As if I am 101% sure about the type.
    I wonder if the results differ with value types instead.
    Also, when the object is null, the .GetType() throws, is operator returns false, as operator returns null. So if there might be nulls in a collection, I do not think GetType is a good idea.

    • @nickchapsas
      @nickchapsas  Před rokem +38

      Unsafe will get a video fairly soon and I will mention it. I didn’t add it in the video because someone will see it, use it as gospel and then shoot themselves on the foot

    • @leandroteles7857
      @leandroteles7857 Před rokem +18

      Unsafe.As is the fastest possible thing because it is a no-op at runtime, but as the name it says it's unsafe, and super easy to be used wrong. You have to be like 200% sure, and if you don't control the object that you're going to cast, you simply can't.
      Also Unsafe.As can be used not only on the lambda expression, but also on the enumerable itself. You can directly unsafe-cast List into List and it will work just fine, eliminating the linq calls, and therefore, with zero allocation.
      But it only works if the type of the enumerable is a reference type, trying to cast List into List will compile, but fail miserably at runtime, even if the list contains ints (because they are boxed).

    • @alphaanar2651
      @alphaanar2651 Před rokem +3

      @@nickchapsas Ah, cool. And you are right about misusing this kind of class/methods.

    • @alphaanar2651
      @alphaanar2651 Před rokem +4

      @@leandroteles7857 I am fully aware of how it works and how else it can be used :).
      You would have already thrown type safety outta window, right when you typed unsafe.

    • @leandroteles7857
      @leandroteles7857 Před rokem +6

      @@nickchapsas A good way to use Unsafe is with generics, to cast the generic thing into its real type. I like to use the second variant of Unsafe.As and do something like:
      if (typeof(T) == typeof(int)) doSomethingWithInt(Unsafe.As(ref paramOfTypeT));
      At runtime the branch will be eliminated and the cast will become a no-op. Even the core library uses this trick in some places.

  • @UrielZyx
    @UrielZyx Před 4 měsíci

    Worth noting that the last strategy you introduced (GetType) is semantically different than all the others.
    If tomorrow someone introduces `class Worker : Person`, you won't get that worker in the resulting list...

  • @imensonspionrona2117
    @imensonspionrona2117 Před rokem

    Great work!

  • @ronnyek4242
    @ronnyek4242 Před rokem

    I think the comment about doing your own benchmarks is good advice in general. Thanks

  • @0shii
    @0shii Před rokem

    Interesting - Certainly did not expect that an OOTB linq method would be slower than just combining two other OOTB linq methods!
    Probably worth adding in a percentage of negative cases appropriate for your domain before making a final determination on the performance though...

  • @benjamininkorea7016
    @benjamininkorea7016 Před rokem +1

    Absolutely insane. I was proud to already know if (X is Y newname), but OfType() blew my mind because I've never encountered it before. I run a Blazor English website with many different types derived from a "Question" base class, and OfType() is going to make my code so much better organized and nicer! I currently use a Where() statement, but OfType() is just such a nice semantic.

    • @yobofunk5689
      @yobofunk5689 Před rokem

      Use oftype a lot with datatable rows oftype

  • @JVimes
    @JVimes Před rokem

    Love to see optimization enthusiasm that acknowledges readability.

  • @denisosipenko7413
    @denisosipenko7413 Před rokem

    Great! Thanks a lot, it's a really usefull matherial.

  • @TheMAZZTer
    @TheMAZZTer Před rokem

    Should be noted that typeof(X) == x.GetType() only returns EXACT type matches. So a bad idea if you have or might have subclasses since they won't match.
    You can do typeof(X).IsAssignableFrom(x.GetType()) instead which will match more like you'd expect, but it is probably slower.

  • @ovader9059
    @ovader9059 Před rokem

    Reflection bit had me surprised!

  • @Muthukumaransubbiah
    @Muthukumaransubbiah Před rokem

    Thank you for this! Super cool video! A+++

  • @anon-qn5fc
    @anon-qn5fc Před rokem

    nice c# casting video, I enjoy

  • @Faygris
    @Faygris Před rokem

    Great video! Thank you so much!
    So you've been using only LINQ for the enumerable types.
    But what's with _(List)StaticObjects.People_ and the equivalents with _as_ and _is_ ?

    • @leandroteles7857
      @leandroteles7857 Před rokem +1

      This will throw because the real type of the object is List, not List, even though it contains only "Person"s. It would only have worked if the object was originally a List that got covariantly-casted into "IEnumerable".

    • @Faygris
      @Faygris Před rokem

      @@leandroteles7857 Of course! You're right

  • @jerryjeremy4038
    @jerryjeremy4038 Před rokem

    Youre the best online teacher

  • @antonmartyniuk
    @antonmartyniuk Před rokem

    Nice video!

  • @slipoch6635
    @slipoch6635 Před rokem

    re: the collection, can you do this without a select statement? As I always find if I include select (.net framework primarily still) it ends up blowing out ram and cpu time.

  • @vandermjr
    @vandermjr Před rokem

    Under the Linq code: "return StaticObject.Person.OfType" and "return StaticObject.Person.Cast" we see the statement "Is": " if (obj is TResult result) return yeld result".

  • @gordonfreimann
    @gordonfreimann Před rokem

    You post new videos faster than my compiler compiles my code.

  • @nguyenquangchienk17hcm88

    Hey Nick, can you share your Rider's theme? Mine looks a bit like Java and I love your version more.

  • @CabbageYe
    @CabbageYe Před rokem +9

    Nick I heard there's a big performance boost when you mark classes as sealed, do you(or anyone else) know anything about that

    • @nickchapsas
      @nickchapsas  Před rokem +20

      There is a video coming on this topic. It’s a bit deeper than that and I wanna touch on language design a bit too

    • @leandroteles7857
      @leandroteles7857 Před rokem +3

      There is a boost because the runtime can optimize it into a simple type check, something equivalent to "obj.GetType() == typeof(SomeClass)". But if SomeClass is not sealed, then the runtime has to traverse all the class hierarchy of "obj" until it reaches "object", to ensure that it is not a "SomeClass".
      How big of a boost this will be, only benchmark will tell. If the type will be exactly "SomeClass" for like 90% of the time, the difference is likely to be negligible.

  • @GameDevASMR
    @GameDevASMR Před rokem

    Interesting. I'm not surprised Harcast_TypeOf being the fastest, as you don't check for null cases when getting type, plus it doesn't support inheritance or interface cases.

  • @rade6063
    @rade6063 Před rokem

    Hey Nick, great video. I have a question regarding unit test and integration test courses. Do you plan on adding videos for testing endpoints (from fast endpoints library) and should those be integration or unit tests? I tried unit testing them but since HandleAsync doesn't return anything I cant really test them with unit tests or am I missing something.

    • @nickchapsas
      @nickchapsas  Před rokem +1

      I’d have integration tests on that level generally speaking

    • @taciolitke
      @taciolitke Před rokem +1

      Regarding methods that doesn't return anything, using mock in your dependencies you can test the number of times a dependency method has been called or threw an exception in your dependencies as logger, services, repositories or handlers. Maybe it might make sense for your context

  • @user-mk3mj7so1i
    @user-mk3mj7so1i Před rokem

    Братан, хорош, давай, давай, вперёд! Контент в кайф, можно ещё? Вообще красавчик! Можно вот этого вот почаще?

  • @FlexNiko
    @FlexNiko Před rokem

    whats that "default!" on the property in the first class you created?
    google only shows me the default params for functions :D

  • @robertmckee9272
    @robertmckee9272 Před rokem +1

    Wondering why you didn't benchmark People.Cast().ToList(); which I would suspect that would be the fastest. Of course that only works where all the elements are of Person type, but that is pretty common in the code bases I've worked on in the past.

    • @nickchapsas
      @nickchapsas  Před rokem +2

      It’s not the fastest

    • @robertmckee9272
      @robertmckee9272 Před rokem +1

      @@nickchapsas Interesting. I guess that shows the importance of benchmarking. I viewed the Cast method as internally doing a Select(x=>(T)x), but it does not, although I'm not sure why the SelectListIterator is so much faster than the CastIterator. Here are my results:
      | Method | Mean | Error | StdDev | Allocated |
      |---------------- |----------:|---------:|---------:|----------:|
      | OfType | 201.27 us | 4.006 us | 7.426 us | 256.41 KB |
      | Cast_As | 211.30 us | 2.018 us | 1.789 us | 256.44 KB |
      | Cast_Is | 216.41 us | 2.610 us | 2.314 us | 256.44 KB |
      | HardCast_As | 94.83 us | 0.740 us | 0.618 us | 256.47 KB |
      | HardCast_Is | 93.93 us | 0.901 us | 0.703 us | 256.47 KB |
      | HardCast_TypeOf | 85.21 us | 0.783 us | 0.733 us | 256.47 KB |
      | HardCast_Cast | 172.42 us | 2.153 us | 2.014 us | 256.41 KB |
      | HardCast_Select | 41.29 us | 0.299 us | 0.265 us | 78.25 KB |

      [Benchmark]
      public List HardCast_Cast()
      {
      return StaticObjects.People
      .Cast()
      .ToList();
      }

      [Benchmark]
      public List HardCast_Select()
      {
      return StaticObjects.People
      .Select(x => (Person)x)
      .ToList();
      }

  • @jongeduard
    @jongeduard Před rokem

    If your goal is to really write the fastest code possible with collections or enumerables, you simply have to step back from LINQ at all.
    For the best performance, you will not write your code in the declarative, functional way of programming, but you'll just need to go old school in the imperative way, by using for or foreach loops and write your conditional statements and type casts inside that.
    LINQ is built to be super handy, to drastically improve your productivity, and still have reasonable performance. But it will and can never really outwin the old way.

  • @Havie
    @Havie Před rokem

    U r the man

  • @rick2591
    @rick2591 Před rokem

    What approach can I take when I do not know the objects that are going to be in a class. Is it Okay to use reflection in that case to get the names of the objects

  • @the-niker
    @the-niker Před rokem +1

    Thing is "as", "is" and hard cast will all cast a derived class to a base class while == typeof(baseclass) would fail. So you are skipping inheritance check there which may not be what you want.

    • @MrDaedra88
      @MrDaedra88 Před rokem

      It will because that example uses hard casting in Select

    • @the-niker
      @the-niker Před rokem +1

      @@MrDaedra88 nope, the Where filter would ignore inheritance and the list would be empty if you're casting to a base class.

  • @tanglesites
    @tanglesites Před rokem

    Nick I know his off topic, but I am having a hard time wrapping my head around the Onion Architecture, and how to organize my project. I have researched it online and found different opinions.
    The goal is to have the flow of control start from the outside at the presentation layer and communication only goes inward and what is inside does not reference what is outside, Presentation -> Service -> Domain ... But the presentation and the Infrastructure are on the same tier ?? I am confused. Is this the same as the N-Layered architecture.. is this a logical organization?? If you can answer or make a video about this... This just don't teach this stuff in school.

  • @HuntingKingYT
    @HuntingKingYT Před rokem +1

    But what with sealed classes? How do *they* perform?

  • @ahmedhafez8698
    @ahmedhafez8698 Před rokem

    WORKS 100%

  • @andytroo
    @andytroo Před rokem

    would checking for interface implementation change these values?
    what about parent/child types ; what if Nick isn't a Person, but an Educator - some of these checks succeed/fail different ways?

  • @j1shin
    @j1shin Před rokem

    But in case of enumerables, the question now is why is OfType slower than HardCast_Is and why is your UI then hinting towards changing HardCast_Is to OfType? Did I miss something?

  • @PauloMorgado
    @PauloMorgado Před rokem

    How does that all play when implicit and explicit type cast operators are defined?

  • @owns3
    @owns3 Před rokem

    I'd be curious if the type was sealed if there's a "big" difference

  • @29Aios
    @29Aios Před rokem

    9:31 Seems there is no check for x on null value at 81' line, however "is Person" or "as Person" has it inside.
    PS. It would be nice to see what the ASM code is generated for all the methods, not for me, but for the subscribers

  • @yummybunny7351
    @yummybunny7351 Před rokem +4

    What "!" mean in "default!" ? At 1:00

    • @jongeduard
      @jongeduard Před rokem +1

      Using the null forgiving operator feels always a bit like kind of a bad practice to me, because you're suppressing a feature that you have enabled to help you.
      So I tend to always be very cautious with using it.
      But there are cases where you simply know it better than the compiler and if you are absolutely shure you can enable it. Keep in mind that by later changes to your code the null checks are still being suppressed, so when situations change to that the something can be actually null, you'll never know because you supressed it.
      But setting default nulls on properties can be a useful action in some cases.

  • @freddyflares2757
    @freddyflares2757 Před rokem +1

    I was waiting for the dynamic keyword to make an appearance and the double dispatch pattern.
    protected override void OnDispatch(object thing) => OnSomething((dynamic)thing);
    void OnSomething(Person person) { Console.WriteLine(person.Name); }
    It's not _that_ slow.

  • @ricardopieper11
    @ricardopieper11 Před rokem

    For GetType() == typeof(Person) I think this is almost a simple integer comparison of pointers? .GetType() should be super fast, I think it's just a reference/pointer of a Type object already loaded in memory, and .Equals on Type is just ReferenceEquals of objects... looks like a simple pointer equals check.

  • @JonathanPeel
    @JonathanPeel Před rokem

    I appreciate this video.
    I am going to remember these results for when I might need it.
    I will probably stick with OfType for most queries, and take the safety over speed.

    • @brtk7
      @brtk7 Před rokem

      You’ll never gonna needed in real life applications, better spend time on defining low coupled contexts with high cohesion than thinking about these benchmarks but somethimes if you’re doing a lot of heavy casting and cannot avoid it then yes better keep that in mind and benchmark your code as well.

    • @evancombs5159
      @evancombs5159 Před rokem

      ​@@brtk7 That is not true, I was just dealing with this last week. When you deal with big data a slight performance gain can save you money.

    • @brtk7
      @brtk7 Před rokem

      @@evancombs5159 If you’re doing something performant critical then indeed diving into IL is reasonable. There is many cases like method lengths that disable method inlining etc. it’s hard but if know .net well it’s doable. Interesting thing I found
      „The IL is only describing what happens in terms of some abstract virtual machine. It may (or may not!) have no resemblance to the machine code that comes out the other end. (An easy way to view the generated code is to break on the start of the method and look at the code in the Disassembly debugger window. Make sure you *disable* "suppress JIT optimization on module load" to get the optimized version.)”

  • @br3nto
    @br3nto Před rokem

    Is there a reason they don’t they update the implementation of OfType() to one of those faster methods?

  • @pkonstantellos
    @pkonstantellos Před rokem +9

    As mentioned in the video, one should not optimize code for such a small performance gain. The main reason is that the language itself is changing over time. Thus, "slower" operations in the current version may be "faster" in a newer version.

    • @29Aios
      @29Aios Před rokem

      Sure, and you are right.
      PS. In my current project, I'm receiving 700'000 Kafka events per second, had to replace properties to fields, removed all async methods, and replaced throwing exceptions to return values using Result, it worked, but still have many service instances.

  • @saurabhchauhan232
    @saurabhchauhan232 Před rokem

    Can you make one video on salting and hasing password to store in db?

  • @syrymzholimbetov8860
    @syrymzholimbetov8860 Před rokem

    👍

  • @pw.70
    @pw.70 Před rokem

    🌬🧠 = Mind_Blown...

  • @jeronimojunior
    @jeronimojunior Před rokem

    1:51 GUARANTEED! 😆😆😆

  • @parkercrofts6210
    @parkercrofts6210 Před rokem

    ice its actually working, im suprised

  • @myemailvl
    @myemailvl Před rokem +3

    In my opinion high level programming languages was made in purpose for people to make clear, easy understandable code. And compiler, runtime and all other things is responsible for performance. You just need to know what you should not do so you not making stupid things. In this kind of languages when you choose between clear code and better performance, you almost every time need to choose clean code.

    • @nickchapsas
      @nickchapsas  Před rokem +5

      And that’s totally fine, but there are always benefits in looking under the hood and understanding things better for our own future use and elimination of false assumptions

    • @alphaanar2651
      @alphaanar2651 Před rokem +6

      C# surely has low-level aspects too. Really lots of people care about performance and try to minimize allocations/computations even if it can make it somewhat less readable.

    • @phizc
      @phizc Před rokem

      If you weren't able to use low level tricks to get better performance in a high level language, that language would be unusable for a lot of purposes, e.g. games.
      By all means, if you make a library you wouldn't want to expose those things. E.g. use _ref_, not pointers.

  • @williamliu8985
    @williamliu8985 Před rokem

    Just curious why not msft just make them the same underlying implementation if most of these commands are doing the same thing...

    • @evancombs5159
      @evancombs5159 Před rokem

      I can understand why the more manual ways may not want to be optimized. There might be some implementation detail that prevents it. What doesn't make sense is why the more declarative method does not use the most efficient casting.

  • @osman3404
    @osman3404 Před rokem

    I go with whatever reshaper refactoring suggests

  • @andrewmaksymiuk986
    @andrewmaksymiuk986 Před rokem

    You didn't mention the switch pattern casting but it's probably just syntactic sugar for one of these anyways

    • @nickchapsas
      @nickchapsas  Před rokem

      Yeah switch is just the same as match casting

  • @rngesus8057
    @rngesus8057 Před rokem

    i purely use .OfType to filter out nulls lol

  • @efrenb5
    @efrenb5 Před rokem

    Old school > syntactic sugar. 'Nough said. LOL

  • @science_and_technology6

    What are the complete steps to create a PayPal adder money program?

  • @EverRusting
    @EverRusting Před rokem

    TL;DW: JetBrains insults you with your every key press

  • @boxacuva
    @boxacuva Před rokem

    I think pretty much all of them are valid ways and context dependent to cast. Maybe there is 1 that should be avoided.

  • @refactorear
    @refactorear Před rokem

    5:23 Hard to talk about clean code when having "object" in your code

  • @qm3ster
    @qm3ster Před rokem +1

    The simplest/shortest/most specialized standard library method should also be the fastest.
    This is an enormous failure on the part of the standard library/compiler/runtime.

  • @ibrahimhussain3248
    @ibrahimhussain3248 Před rokem

    What the heck is default! ?

    • @phizc
      @phizc Před rokem +2

      The exclamation point is the null forgiving operator. It suppresses the warning that the property could be null.
      It's basically setting the field to null but tells the compiler "I know what I'm doing".

    • @ibrahimhussain3248
      @ibrahimhussain3248 Před rokem

      @@phizc thanks :)

  • @alluseri
    @alluseri Před rokem

    unchecked casts are supreme and you don't even know about them smh

  • @davidwright5719
    @davidwright5719 Před rokem

    Don’t use Linq. Seriously. It just obscures and genericizes the logic that is used for collection processing. Actually think about and make your collection processing logic explicit.

  • @Waffle4569
    @Waffle4569 Před 5 měsíci

    Unsafe.As is by far the fastest.

  • @Fikusiklol
    @Fikusiklol Před rokem

    Hey, Nick!
    New comer here :)
    Tried this and resuted even faster.
    public List Cast_Span()
    {
    var list = new List();
    foreach (var item in CollectionsMarshal.AsSpan(StaticObjects.People))
    {
    if (item is Person person)
    {
    list.Add(person);
    }
    }
    return list;
    }

  • @adamponka6404
    @adamponka6404 Před rokem

    Just as I thought adding `sealed` keyword to make the `is` operator work like comparing to specific type, speeds up the hard casting by 15%. Here are my benchmarks with and without the `sealed` keyword:
    | Method | Mean | Error | StdDev | Gen0 | Gen1 | Gen2 | Allocated |
    |------------------ |---------:|--------:|--------:|--------:|--------:|--------:|----------:|
    | HardCast | 182.6 us | 3.59 us | 5.26 us | 83.0078 | 82.5195 | 41.5039 | 256.47 KB |
    | CompareType | 151.4 us | 1.66 us | 1.47 us | 83.0078 | 82.5195 | 41.5039 | 256.47 KB |
    | HardCastSealed | 153.5 us | 1.46 us | 1.22 us | 83.0078 | 82.5195 | 41.5039 | 256.47 KB |
    | CompareTypeSealed | 147.5 us | 2.85 us | 4.17 us | 83.0078 | 82.5195 | 41.5039 | 256.47 KB |

  • @artemivanov2141
    @artemivanov2141 Před rokem

    Why you use default! in "public string FullName { get; set; } = default!;" ??? ​ @nickchapsas

    • @nickchapsas
      @nickchapsas  Před rokem

      Because this is a not null value so I default it as such

    • @artemivanov2141
      @artemivanov2141 Před rokem

      @@nickchapsas thanks! I'm not used to non-nullable types yet (

  • @lucwidmer6294
    @lucwidmer6294 Před rokem

    How about doing an episode between ToList() and ToArray(). Everybody always seems to use ToList() but I would really expect ToArray() to be more efficient im many scenarios where you don't change the collection anymore after it's created. I really enjoy your work.

    • @nickchapsas
      @nickchapsas  Před rokem +4

      Be sure that a video covering the topic is coming soon