What are the Frozen Collections coming in .NET?

Sdílet
Vložit
  • čas přidán 14. 12. 2022
  • Join the NDC Conferences Giveaway: mailchi.mp/nickchapsas/ndc
    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 give you a preview to the brand new Frozen Collections coming in .NET 8. The main two types are FrozenSet and FrozenDictionary and in this video we will see what they do, why we need them and how they perform to understand how they fit in our applications.
    Workshops
    NDC London | 23-27 January 2023 | bit.ly/ndclondon2023
    dotnetdays | 20-21 April 2023 | bit.ly/dotnetdays2023
    NDC Oslo | 22-26 May 2023 | bit.ly/ndcoslo2023
    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 • 188

  • @capsey_
    @capsey_ Před rokem +219

    Nick is like that one adult that shows you cool dangerous stuff when you are a kid and asks you to not tell anyone or they will get in trouble

    • @jpsytaccount
      @jpsytaccount Před rokem +2

      Muahahah

    • @csexton07
      @csexton07 Před rokem +9

      I do appreciate him showing that though, I find it pretty cool.

    • @srtghfnbfg
      @srtghfnbfg Před rokem +6

      Well If you have any basic C++ knowledge you'd understand that it's basically a pointer to the data so of course you can modify it. It's almost the same with Java reflection where you can access private elements 😂 Frowned upon doesn't mean impossible

    • @csexton07
      @csexton07 Před rokem +1

      @@srtghfnbfg personally for me I understand pointers from knowing how the stack and heaps work without any c++ knowledge. You see enough null reference/pointer exceptions you sort of pick up on it over time. Just very basic knowledge...

    • @RhymesWithCarbon
      @RhymesWithCarbon Před rokem

      Playing with fire: you could, but why?

  • @needsloomis7164
    @needsloomis7164 Před rokem +4

    To clear up some misunderstanding, in functional languages like F#, you don't mutate data, but you do use functions that return modified copies of it. C# is a hybrid language with many functional tools to support functional patterns, so having an "immutable" suffix to differentiate between mutable and copy only makes sense.
    So why not just replace immutable with frozen? We'll then we'd all just write helper functions to do our functional programming and be right back where we started, but likely with less efficiency.
    So what even is the point of having frozen? To quote the original proposal "There are many scenarios where collections are initialized during startup, or during major state changes in the application, and are not mutated afterwards. Taking advantage of this pattern can lead to substantial improvements in overall access performance of the collections." This is also the reason frozen sets are *very* slow to create.
    So with that in mind, think of Frozen less as an alternative to immutable objects, and more as a fast access const for data sets.

  • @Dato0011
    @Dato0011 Před rokem +15

    Nick 's channel is a gold mine. I find that any video I pick contains valuable information

  • @Vastlee
    @Vastlee Před rokem +91

    This is good to know, but I have to be honest... the functionality of the FrozenCollections is exactly what I would expect the Immutable versions to do. That expectation has & will almost certainly lead to future issues. The whole thing sounds like a naming mistake that they can't correct now.

    • @Warkenji
      @Warkenji Před rokem

      it’s still an alpha version 😅

    • @agsystems8220
      @agsystems8220 Před rokem +20

      Not really, though it doesn't make much sense unless you come from a functional background. The point is that a reference to an immutable object will always do the same thing, and that does apply here. Instead of adding to the set that all existing references point to, the immutable add method returns a whole 'new' set object that behaves as the old set after this operation, but it does this without affecting existing references. The naive implementation of a functional language would copy the whole object every time you 'modify' it, where this does something cleverer, but programmers can think in terms of a new object always being created, rather than anything being modified*. This has advantages, but that is getting into the woods, so to speak.
      For example, in a functional language, the psudo code:
      x=""
      x=x+"a"
      y=x
      x=x+"b"
      would end up with x being a reference to "ab", but y would still be a reference to "a". In a language with mutability the later modification of x might show up at y. Immutability isn't about telling a programmer that they can't modify something, it is a guarantee that something you hold will not change under your nose.
      The point is that it allows us to construct large immutable structures in steps (even loops) without dropping immutability at any step. Here the structures were cast directly from a mutable one that was mutated iteratively, but in some languages (lazy languages Haskell in particular) you cannot do that. That is the pattern immutable structures are designed for.
      *In actual fact it will first check whether any references to the object exist. If they do it will leave it, create a new object is a pair of it and a change to it, and then return a reference to that new object. If no references exist then it will just modify it and return a reference.

    • @ImmoLandwerth
      @ImmoLandwerth Před rokem +22

      You can blame me for that… our immutable collections are really what academia calls persistent collections, which is focused on sharing state between different “mutated” versions (except for immutable array, which always does a full copy). The rationale was that the term “immutable” is till true, “persistent” is too esoteric.
      Sadly, at the time we didn’t optimize the collections for perf (we kinda did, but the benchmark was F#, not arrays and dictionaries). Still, they have served us well and continue to do. I’m not entirely sure I’ll regret this, but I also know I’ll be using FrozenDictionary a lot.

    • @Blaisem
      @Blaisem Před rokem +2

      @@ImmoLandwerth Interesting bit of history; thanks for sharing! Persistent does sound like the perfect label, now that you mention it, although I guess that's why it's used in the academia 😅

    • @jonathan55555
      @jonathan55555 Před rokem

      There is also ReadOnlyDictionary to add to the confusion

  • @billy65bob
    @billy65bob Před rokem +8

    I've mostly tackled this by returning IReadOnlyCollection from my methods; unfortunately it does mean that bad actors can easily cast it back to a RW version...
    I've wanted proper read only hashsets for a long time, so I'm glad to see it is finally a thing.

    • @qj0n
      @qj0n Před rokem +7

      On the other hand - bad actor will always be able to shoot themselves in the foot. Casting IReadOnlyCollection to mutable RW one should always ring a bell

  • @GameDevNerd
    @GameDevNerd Před rokem +3

    What you mean "Only if you really know what you're doing?" ... I literally just watched a Nick Chapsas video, of course I know what I'm doing!

  • @azaraba9716
    @azaraba9716 Před rokem +2

    1. An array declaration is written shorter.
    2. Calling Array.IsExists or Enumerable.Contains is sufficient in most cases.
    3. Do you want to protect the parameter from being changed and therefore don't want to use an array? Just don't change the passed parameters.
    4. Do you really want to protect the parameter from being changed? Submit a copy.
    5. This is a very large and important collection that is used a lot in the code, and you don't want to copy it? Try wrapping it in a provider with IsExists methods and the like.
    6. In the name of performance, don't you want to do (5)? Congratulations. In your very rare case, there will be a thousand cases where the short
    int[] Tada(int[], int[])
    has been replaced with the wonderful
    ImmutableHashSet Tada(ImmutableHashSet, ImmutableHashSet)

  • @inzyster
    @inzyster Před rokem +4

    Even though the dictionary was Frozen, I guess he wouldn’t… let it go 😎

  • @erik64329
    @erik64329 Před rokem +1

    I've been a working student in a tech company for a year now. I never thought coding could be this "dangerous" like this. These warnings reminded me of watching mythbusters when they were about to do some dangerous experiments. "Please don't try this at home. We're professionals. You are not!" :D I had to laugth a little bit.
    Maybe I'll show this to my chef/mentor just to see him panic a little bit

  • @Kingside88
    @Kingside88 Před rokem

    Really enjoyed this video. Good explanation!

  • @CDam_S
    @CDam_S Před rokem +1

    love the first quote

  • @fred.flintstone4099
    @fred.flintstone4099 Před rokem +7

    I think it is confusing, there is the "readonly" modifier keyword, then there is ReadOnly[Collection|Dictionary|List], and Immutable[Dictionary|List], and now FrozenDictionary.

  • @paulsanchez5030
    @paulsanchez5030 Před rokem

    I literally have never tried to code with pointers or reference values in C#, this is a nice reminder that there is still a lot of C# that I don't kmow after a lot of years using it. what a language...

  • @RobertPaulsim
    @RobertPaulsim Před rokem

    Nice tips!!!!

  • @AlanDias17
    @AlanDias17 Před rokem

    Yeah those are really good features. Thanks!

  • @affegpus4195
    @affegpus4195 Před rokem +2

    Well... the cold never bothered me anyway

  • @ivaniliev93
    @ivaniliev93 Před rokem +1

    I like the ending of the video. It reminded me of something, perhaps, Nick has discussed it already. In corefx there is a DictionarySlim in which you have a method GetValueOrAddRef, so if there is a value for a given key you get it, if it doesn't exist you can receive back a ref and you can assign it a value, like this you do add or update with one lookup.

  • @F1nalspace
    @F1nalspace Před rokem +8

    Very interesting. We definitily have cases where a Frozen collection would be better suitable.
    But i didn´t expect that the Immutable collections are so slow in lookup methods 😞We use a lot of Immutable arrays and collections all over the place, mostly to prevent data-race conditions when accessing it from multiple threads - especially when its bound to a data source in WPF. Its cool, even though i do programing since 30 years now, i am still learning something new ;-)
    So thanks for sharing.

    • @ImmoLandwerth
      @ImmoLandwerth Před rokem +3

      ImmutabArray is just a very thin wrapper over a raw array; the lookup speed should be on par with regular arrays.
      ImmutableList and ImmutableDictionary are using a tree for sharing data; they performance is O(log n) rather than O(1) which is pretty good, but not as awesome as regular arrays and dictionaries.

  • @josephizang6187
    @josephizang6187 Před rokem

    👍👍 Nick...Nick..than you.

  • @XenidRol
    @XenidRol Před rokem +5

    I like this feature, although this is exactly how I'd like ReadOnlyCollection to behave. Now things are gonna get a little bit messy especially for newcomers.

  • @sgbench
    @sgbench Před rokem +3

    I imagine FrozenDictionary uses information about the data it's initialized with to customize its hashing or build additional data structures that give it its performance boost. So if you change values as you demonstrate here, you may give up some performance or data consistency. I'd be interested in seeing some benchmarks investigating this :)

  • @giorgosfilippas259
    @giorgosfilippas259 Před rokem +1

    Hello Nick! It would be nice if you made a video around the evolution of finalizers(destructor) in c#.

  • @sanjayidpuganti
    @sanjayidpuganti Před rokem

    IMHO Frozen makes sense

  • @DevJungles
    @DevJungles Před rokem +3

    Collections, Specialized Collection, Readonly Collections, Generic Collections, Concurrent Collections, Immutable Collection, and now... Frozen Collections.
    Have I missed smth?

    • @anreton
      @anreton Před rokem

      Sorted collections, Observable collections, arrays (yeah, it's special case).
      ;-)

  • @tedchirvasiu
    @tedchirvasiu Před rokem +1

    Let it goooo, let it goooo

  • @UlrichTonmoy
    @UlrichTonmoy Před rokem

    Its like object pulling of Unity. Instantiate once and then just show it or hide it so no more instantiating everytime you need it. Its not memory efficient but time efficient.

  • @alexb.9806
    @alexb.9806 Před rokem +1

    Thank you for this video, cool as usual!
    But I can't imagine cases, where there will be a significant boost from decreasing access time by 1ns. Maybe just something very specific, like building some sort of a really huge dict (many many gigabytes of RAM) for indexing.
    Btw, how do frozen hashtables handle hash collisions? Maybe there will be the most significant performance boost.

    • @ZintomV1
      @ZintomV1 Před rokem

      Not sure how this scales, but if you have a huge set of millions of items, you could potentially reduce lookup time from say 60 seconds to 30 seconds, big difference.

  • @fullstackcodr6239
    @fullstackcodr6239 Před rokem

    Hello Nick, I really like your videos, congrats for all the good work you are doing.
    It's impressive how much knowledge you have developed around the .NET ecosystem.
    Just a bit of a feedback, I'd suggest you to try and keep consistent speaking rate as I struggle to follow some times.
    When having the playback speed to normal, I find that you are rushing and it's hard for me to follow.
    When I set it to 0.75 it's better but because your speaking rate is not consistent, it get's really slow from time to time.
    Again, thanks for your videos and keep up the good work!

  • @alimohammadizadeh2120
    @alimohammadizadeh2120 Před rokem +2

    Please do the benchmark between dotnet and java

  • @benjaminclehmann
    @benjaminclehmann Před rokem +1

    I'm assuming that most of the performance improvement (and slower init times) is coming from perfect hashing, but I would've been interested to see a little more of that special sauce.
    At any rate, still a good video

  • @Nikkes02
    @Nikkes02 Před rokem +2

    The implementation of the frozen dictionary could one day change, so that the backing memory is actually write-protected after filling it. Therefore, the value reference write method might not work later on. Better not rely on it.

    • @agsystems8220
      @agsystems8220 Před rokem +5

      Never mind the implementation changing, any code down stream might cache something that it actually cannot, meaning some wild bugs might crop up.

  • @bslushynskyi
    @bslushynskyi Před rokem

    I came up with a valid use case of changing value in frozen container (apart from dictionary and set there might other frozen things be added). So if you write a trainer for a game and some data, let's say hp, is stored in frozen dictionary, you can substitute the value with the desired one. In a nutshell, game hacking tools development.

  • @wknight8111
    @wknight8111 Před rokem

    A lot of workloads that I do can be broken down into two distinct phases: First we have some kind of setup (which is one-time and can be a bit expensive) and then we have execution (which often happens in a loop, and needs to be fast). These Frozen collections (and I hate the name "Frozen" for these) really give you the option to optimize runtime with a little more setup expense, and a lot of programs will benefit from that. I just wish that the naming were a bit more clear for everything.

  • @b4ux1t3-tech
    @b4ux1t3-tech Před rokem +6

    I found myself building a constant-time lookup mechanism in C# yesterday for Advent of Code. It ended up being a two dimensional array, since that was all I needed, but I had to do a lot of data cleanup (working in floats) to get it working well.
    Now I see I could have used a hashset. How have I never seen this in a decade of dotnet development?!

    • @srtghfnbfg
      @srtghfnbfg Před rokem

      My guess would be because you graduated in IT and not CS so you didn't study data structures deeply 😂 but that's just my 2 cents and something I've noticed over the year with IT ppl

    • @b4ux1t3-tech
      @b4ux1t3-tech Před rokem +1

      @@srtghfnbfg neither, actually. Self taught developer who ended up doing a degree in software development (not cs) after being in the industry for a little while.
      I was in the process of building a hashset, more or less, for tuples, when I realized that the array would accomplish what I needed, and scrapped the hashset.
      Just confused how I've missed the fact that one of the libraries I use _all the time_ already had what I needed! I've built quite a few hashsets in dotnet for various purposes, and have been meaning to build a generic version for a while. Guess I don't need to.

    • @srtghfnbfg
      @srtghfnbfg Před rokem

      ​@@b4ux1t3-tech Well congratulations already for making it while being self-taught!
      I would still recommend you to develop some data structures, design patterns, architectures for fun during weekends. This teaches you a LOT of how things are implemented behind the scenes and is basically knowledge that can be transferred to any language since it's language-agnostic. IMHO it's quite worthwhile for any developer no matter the origin

    • @b4ux1t3-tech
      @b4ux1t3-tech Před rokem

      @@srtghfnbfg I have been programming for over 20 years. I am very well-acquainted with the data structures and design patterns that are commonly taught in school. Do anything for 20 years and you're bound to pick up the basics.
      My confusion was with the fact that I didn't realize that _dotnet_ had a hashset, not that I didn't know that the concept of a hashset existed.

    • @srtghfnbfg
      @srtghfnbfg Před rokem

      @@b4ux1t3-tech well I'll stop here. It's just that Hashsets and quite a few other structures are in every most used language today, so developing for more than a few months and not knowing a language had them makes me start questioning a lot of things 🧐

  • @chswin
    @chswin Před rokem

    Should of had these a while ago.. we actually made one like a hash set… but required us to essentially write a version of this which is trickier than it appears

  • @TheBreaded
    @TheBreaded Před rokem +2

    God help us having to do any searches for "frozen collection" and not turning up a bunch of kid movie soundtracks.

  • @agsystems8220
    @agsystems8220 Před rokem

    Just looking at some of the other comments, a short demonstrating the different use cases of immutable sets and frozen sets might be warranted.

  • @muhamedkarajic
    @muhamedkarajic Před rokem +1

    I kind of don't see my self using this feature but fear eneugh, better to have it then not to have it. Its eneugh casual and standalone that I don't care.
    Maybe I'll use it, but really the case where you don't wanna 'append' anything to your dictionary is rare. I get the point with changing the values thats really funny and might come in handy. Also it gives me those C++ vibes :)

  • @agsystems8220
    @agsystems8220 Před rokem +2

    I like the thing at the end, but some specifics on why it is a terrible idea might have been worth mentioning; Most code will operate under the assumption that the frozen dictionary will not mutate, so it is safe to cache returns (or the results of some calculation that depends on a return). You can end up with some code written later assuming (reasonably) that they can cache, and this being a bug (Its absolutely your bug, not theirs).
    What might be nice is a non extendable dictionary, similar to non-extendable JS objects. I guess there are intermediate cases where you want a dictionary that's values can be modified, but not it's keys. That should still permit the performance improvements on the keys, while avoiding hacky stuff like this, and explicitly letting downstream users know that they should expect values to change.

  • @f.donnet8165
    @f.donnet8165 Před rokem

    I think I will replace my small Dictionnary stored in MemoryCache by FrozenDics

  • @krzysztofhandzlik9273

    Practical use example would be much more usefull ;) still great video, thanks !

  • @zbaktube
    @zbaktube Před rokem

    Hi! Just curiosity, Is FrozenSet a Tuple with unique elements in it?

  • @mosheritterman3472
    @mosheritterman3472 Před rokem

    Thanks for another great video! Just wondering, if the Contains operation is O(1) how is it that they perform differently?

    • @viktorstojanovic9007
      @viktorstojanovic9007 Před rokem

      Just because algorithms have the same time complexity doesn't mean they execute in the same amount of time. For example let's say that we have two algorithms and both of them have constant time complexity. The first one will always execute in 5ms, but the second one executes in 5 years. They both have constant execution time but the first one is much faster than the second one

    • @mosheritterman3472
      @mosheritterman3472 Před rokem

      @@viktorstojanovic9007 Thanks for responding

    • @viktorstojanovic9007
      @viktorstojanovic9007 Před rokem

      @@mosheritterman3472 no problem

  • @Blaisem
    @Blaisem Před rokem +1

    I'm a noob. Does allocated mean that it stays on the heap forever, or is it just for the timeframe that it is initialized and then the object becomes slimmer? 160-190 Kb on the frozen collections for only 1000 entries seems like a lot depending on how it scales with larger sizes. Linear scaling would mean a gigabyte on your heap if you had a collection with 10+ million elements. Maybe a related question is when does the init occur; when the program is started up or when it's first called in the code?

  •  Před rokem

    I'm starting to have doubts about this and artificial immune types (if I want to protect a collection, I'll return a copy or I'd like to mark what I return as immutable). Also all the struct, class, records - why not just class with flavor like immutable, readonly and let the compiler decide to use a heap on the stack on on the main heap ? C# must be kept simple.

  • @tarun-hacker
    @tarun-hacker Před rokem +3

    Hey Nick, I don’t think changing the value in a dictionary is not an unsafe thing to do as long as the key remains same.
    As in a Dict only keys are hashed right

    • @nigh7swimming
      @nigh7swimming Před rokem

      Depending on the value type, it may not be thread safe.

  • @markv3541
    @markv3541 Před rokem

    I know the warning probably applies to me but im curious, what does Nick mean with that being unsafe?

  • @Dustyy01
    @Dustyy01 Před rokem +5

    So what would be the pros over an IReadOnlyDictionary for example? I mean yes u can change it but same with the FrozenDict (even though it's much more difficult).

    • @nickchapsas
      @nickchapsas  Před rokem +1

      you can change anything on anything during the runtime. That’s not an arguments. The argument is that you really can’t change the frozen dictionary in a safe way or in an accidental one and it has way better performance than the readonly version

    • @Dustyy01
      @Dustyy01 Před rokem

      @@nickchapsas ah that makes sense yea 👍

    • @LeMustache
      @LeMustache Před rokem

      @@nickchapsas You can't accidentally change the readonly collections either if you use .AsReadonly() since it wraps the original collection in another type.
      Does that mean that frozen collections simply offer better performance and they'll make read only collections obsolete?

    • @nickchapsas
      @nickchapsas  Před rokem +2

      @@LeMustache Yeah you can. There is no guarantee that the backing collection isn't mutated at some point during the runtime. You just hope that whoever provided you with the collection doesn't update it in the future. Frozen just doesn't allow you to do that in any capacity. With AsReadOnly, you just get a view of that backing data, but if that data changes then your readonly colleciton changes too

    • @LeMustache
      @LeMustache Před rokem

      @@nickchapsas Got ya. Thanks

  • @metalhead6604
    @metalhead6604 Před rokem

    Thats agreat Madonna reference!

  • @user-dc9zo7ek5j
    @user-dc9zo7ek5j Před rokem +1

    The dotnet team should remove all those collections that are only differentiating by options and make it clear, you have mutable dictionary, and immutable one. The immutable classes that are present are valid in their implementation, but sadly they don't offer anything more aggressive by being immutable, nor are semantically correct, because they are holding objects that can mutate both their equals and hashes by changing their members anyways. Maintaining 10 different types of dictionary seems like a crazy idea that needs to stop, it also dilutes the codebases and confuses people. Just like the Stream class, which, if you want to implement you must override 20 different write methods, with array, span, memory, readonlyspan, readonlymemory... They can instead do a single dictionary which will have "option" class inside it, to handle all the cases, concurrent, read only, immutable and so on, plus, we don't have to be so much dummy proof, IReadOnly works just fine. They should focus on being more straighforward, one way of doing things, and to stop adding features, because the libraries that they made are more than perfect, the problem is adding the debt that will spead to the users.

  • @TheBurzhuy
    @TheBurzhuy Před rokem

    LOL, the extension that modifies this collections should have name MeltAndWrite 🤣

  • @kchrsat
    @kchrsat Před rokem

    @Nick, have you tried to add IReadOnly* interfaces of Dictionary to your benchmarks?

    • @nickchapsas
      @nickchapsas  Před rokem

      I have but I don’t even consider them as a solution to this problem because they are not. Readonly collections are just views over mutable data. They are not immutable. The user can always cast to the backing type and edit them at any point

  • @Cafe-O-Milk
    @Cafe-O-Milk Před rokem

    Something interesting to be used in the Startup. This could possibly replace the app config object initialization as a singleton?

    • @nickchapsas
      @nickchapsas  Před rokem +1

      App config is actually mutable during runtime

    • @Cafe-O-Milk
      @Cafe-O-Milk Před rokem

      @@nickchapsas Thanks for that!

  • @engineeranonymous
    @engineeranonymous Před rokem +1

    If you want to change constant variables, if there is a will there's a way 😁

  • @andrewogu6451
    @andrewogu6451 Před rokem

    Una never talk wetin dey hungry una! 🙈 😂😂

  • @rogeriobarretto
    @rogeriobarretto Před rokem +4

    Although I don't rely on Unsafe ways of accessing reference, this is quite interesting for very niche scenarios. Always appreciate your content Nick, top notch, Thanks!
    Just curious that now we have Immutable and Frozen, those terms obviously are conflicting and I can see in a longer term .Net Core start considering breaking changes.

    • @nickchapsas
      @nickchapsas  Před rokem +3

      They could never make such a change because it would be insanely high impact. I am assuming they went with Python's naming with uses the same Frozen word for their immutable set

    • @diadetediotedio6918
      @diadetediotedio6918 Před rokem

      I think both have their use cases, ImmutableCollections are memory efficient and FrozenCollections are speed efficient

    • @nickchapsas
      @nickchapsas  Před rokem +3

      @@diadetediotedio6918 Memory doesn't matter if you are only gonna allocate it once and maintain it for the lifetime of the application. Immutable's O(log n) is terrible compared to frozen's perf

    • @capsey_
      @capsey_ Před rokem

      @@nickchapsas i wonder why immutable's speed is so terrible? what is the reasoning behind using a tree structure?

    • @diadetediotedio6918
      @diadetediotedio6918 Před rokem +2

      @@nickchapsas
      But memory consumption matters a lot if you are going to manipulate a lot of immutable collections in a more functional style of programming, this is where immutable collections tend to shine, you can manipulate them relatively lightly (naturally not as much as mutable and frozen versions) while being incredibly memory efficient.

  • @logicalfalse
    @logicalfalse Před rokem

    What interfaces are implemented for Frozen collections? Have they created a true list interface that is read only and guaranteed not to to change?

  • @cocoscacao6102
    @cocoscacao6102 Před rokem +1

    Wait... why would immutable hash/dict be slower than the mutantable one?

    • @ewdlop1
      @ewdlop1 Před rokem

      AVL Tree implementation

  • @justicefreeman6598
    @justicefreeman6598 Před rokem

    .NET 8 already? I can only imagine to use .NET 5 in my company projects. By the way, I could not find the information about .NET 8 or planning new features

  • @urbanelemental3308
    @urbanelemental3308 Před rokem +1

    You didn't compare the access speed of a FrozenDictionary against a standard Dictionary.
    How much difference? I'd still like to see a comparison against arrays.

    • @nickchapsas
      @nickchapsas  Před rokem +5

      Dictionary_ContainsKey: 2.945 ns
      FrozenDictionary_ContainsKey: 2.060 ns
      Dictionary_Get: 2.982 ns
      FrozenDictionary_Get: 2.259 ns

    • @urbanelemental3308
      @urbanelemental3308 Před rokem

      @@nickchapsas I wonder why this couldn't be released as a .NET Standard package. :/

  • @lordicemaniac
    @lordicemaniac Před rokem +2

    So how frozen collections compares to ReadOnly collections? And also, I can't help it.... LET IT GOOOOO, LET IT GoOoOOOO :D

    • @nickchapsas
      @nickchapsas  Před rokem +2

      Frozen Colletion are truly immutable. ReadOnly collections are just views over backing data that can change and that change will be reflected to the readonly collection

  • @adrian_franczak
    @adrian_franczak Před rokem +1

    what about dict fo frozen dict performance?

    • @nickchapsas
      @nickchapsas  Před rokem

      Dictionary_ContainsKey: 2.945 ns
      FrozenDictionary_ContainsKey: 2.060 ns
      Dictionary_Get: 2.982 ns
      FrozenDictionary_Get: 2.259 ns

  • @andersborum9267
    @andersborum9267 Před rokem +1

    What's the reason they're introducing yet another category (i.e. "Frozen") instead of going with "ReadOnly", as is already the case?

    • @nickchapsas
      @nickchapsas  Před rokem +3

      Because ReadOnly already have a behavior which is that they are readonly views over potentially mutable data that can change and be reflected on the readonly collection

    • @andersborum9267
      @andersborum9267 Před rokem

      @@nickchapsas ah yeah, I was off my mental game for a bit; totally forget that ReadOnly variants are just views over what's basically mutable data.

  • @AvenDonn
    @AvenDonn Před rokem

    I can already see that ref magic being used to fix bugs in production because nobody dares actually touch the design issue

  • @csexton07
    @csexton07 Před rokem

    The only real benefit I see over ReadOnlyDictionary is the performance aspect. I won't be using the Frozen stuff unless I absolutely need to for performance reasons such as a heavily used api endpoint.

    • @nickchapsas
      @nickchapsas  Před rokem +4

      ReadOnly collections are just views over potentially mutable data. If you change the backing data of a readonly collection the the readonly collection will reflect that change. Frozen collections truly abstracting all that away and don't allow you to change the data.

  • @TheBurzhuy
    @TheBurzhuy Před rokem

    readonly , immutable, frozen. What's next? WePromiseYouCantChangeItCollection then WeSwearToGodThisIsReadOnlyCollection, DontEvenTryToChangeThisShitCollection (with another way to change it)?
    I would happy if there was a native array with no writing by index capabilities, a truly read-only array which has the same memory usage and performance. Sometimes I really need this but now I have to return either interface (which allows to cast it back to array and change) or some custom wrapper to really prevent easy modifications which leads to +1 object per each case of usage.

    • @TheBurzhuy
      @TheBurzhuy Před rokem

      CastInStone - sounds really read-only

  • @dank696969
    @dank696969 Před rokem

    I am guessing these are written to use Spans under the hood?

    • @nickchapsas
      @nickchapsas  Před rokem +4

      I was acutally meant to show this but I forgot. FrozenSet is using an array to store the items which later seems to be wrapped in an ImmutableArray and the FrozenDictionary uses an array for the keys and and array for the values which in both cases are wrapped in an ImmutableArray

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

    Nick was just put on a naughty list for showing us how to mutate the immutable.

  • @miroslavmakhruk4102
    @miroslavmakhruk4102 Před rokem

    Well... As an assembly guy (in the distant past) I don't think references are scary... 🙂Never felt bad about pointers in C and C++, and see no reason to start feeling bad about them in C#. 🙂

  • @killymxi
    @killymxi Před rokem

    I understand they most likely needed some new name, because they ran out of better names from previous attempts.
    But for me the "Frozen" word associated with certain JavaScript feature that makes collections to throw errors on modification calls.

    • @vanstrihaar
      @vanstrihaar Před rokem +1

      Whereas for me it smth similar to WPF freezable. Why not to call it just readonly

    • @killymxi
      @killymxi Před rokem

      @@vanstrihaar yeah, both WPF and JS imply something can exist in a regular state and be frozen later, whereas the whole point of new collections is that they are immutable from construction and can use stronger guarantee of immutability for performance optimization.
      There are existing wrapper classes like ReadOnlyCollection and ReadOnlyDictionary.
      Even if they introduce new ones in a different namespace, that would still be confusing. That's my guess.

  • @stoic7810
    @stoic7810 Před rokem

    You would typically have to use "Contains" on the frozen set at least 44000 times to just make up for the initial creation overhead over hash sets.

  • @knok2222
    @knok2222 Před rokem

    How much to get you to fly to Washington and hang out on my team for a few days :P

  • @roelbrook7559
    @roelbrook7559 Před rokem

    My first thought was "hmm, what would happen if I cast it to a void pointer"?
    Also, what were they thinking with the naming of ImmutableHashSet and friends? They shouldn't have had an .Add or .Remove to begin with.

    • @KanashimiMusic
      @KanashimiMusic Před rokem +1

      I think that's not really true. They ARE immutable. Add and Remove will return a new one, leaving the old one unchanged. I think that's quite practical.
      The thing that REALLY bothers me is the naming of "IReadOnly...".

    • @agsystems8220
      @agsystems8220 Před rokem +1

      It is built to support functional patterns. In functional programming instead of adding something to a set you have a function that takes a set, the thing you want to add, and then it returns a new set that is the old set with the thing included. Importantly it does this without mutating the old set (usually, often it will check whether any references exist, and if none do then it will just mutate it and pretend it didn't). Obviously we don't want to copy a set every time we add a single item (because we are looping), so instead we return a reference to the old set (that cannot change) together with a representation of the change to it.
      You can have whatever functions you like on immutable objects, as long as they return something new rather than mutate the object.

  • @yordantodorov7405
    @yordantodorov7405 Před rokem +2

    If you really really really really really really really really really really know what you are doing ... :) I warned you a couple of times, more like 100 times ;)

  • @Erlisch1337
    @Erlisch1337 Před rokem

    2:23 - thats not ReadLine() :)

    • @B1aQQ
      @B1aQQ Před rokem

      It is for the computer. It's reading your input.

  • @B1aQQ
    @B1aQQ Před rokem

    That ref thing would never pass a pull request review.

  • @PanzerFaustFurious
    @PanzerFaustFurious Před rokem

    Why don't they just improve the immutable classes?

  • @yoel.taylor
    @yoel.taylor Před rokem

    Nick for the love of god update your plugins :)

  • @Khitiara_
    @Khitiara_ Před rokem +2

    ive been using a library for these for months now, glad its getting official support since this is what the immutable collections should have been the whole time

  • @JVimes
    @JVimes Před rokem

    I wonder if you can just wrap it in a mutable collection so nothing sees the frozen collection. Except its own methods, hmm.

  • @KvapuJanjalia
    @KvapuJanjalia Před 11 měsíci

    I don't see any significant improvements in my own benchmarks. I hope I'm doing it wrong.

  • @FarmerSchinken
    @FarmerSchinken Před 7 měsíci

    Another thing that will be used wrong a hundred times for each time it is used correctly. Calling the frozen set lookup "almost half" as fast is not very objective. According to your own data, HashSet is 46% slower in lookup than FrozenSet and FrozenSet is 36% slower than HashSetSet/2. So in a way, calling it "almost half" is about as correct as calling HashSet lookup up "as fast as" FrozenSet lookup....
    Overall you could also say for ten times the initialization time and ten times the memory you get a lookup that still takes 68% of the original time - which sounds way less cool...

  • @michalkowalik89
    @michalkowalik89 Před rokem +1

    They solved a bug in immutable by adding a new class. nice. .NET 8 version indicated backward incompatibility changes so they should fix Immutable

    • @mr.mindor
      @mr.mindor Před rokem +1

      It isn't a bug in immutable so much as perhaps poor naming. Naming is always the hardest part of programming. Add and Remove on an ImmutableSet the Immutable types do not modify the Set, they return a new set that is a modified copy of the original, and the original Immutable remains as it was. It may have been better to use different names for these methods to avoid the naming collisions with the methods of the same name that do modify the non-immutable versions, but what those non-clashing names would be I'm not sure.

  • @RobinHood70
    @RobinHood70 Před rokem

    9:08 That comment didn't age well. 😉

  • @chrism6880
    @chrism6880 Před rokem

    If you know what you're doing well enough to safely mutate the frozen dict, you should know enough to never have to lol

  • @joshcoleman5884
    @joshcoleman5884 Před rokem

    I'm surprised that the performance of the immutable set and dictionary were so much worse. Isn't the point of immutability that you can make certain assumptions to optimize performance? What purpose do they serve now that frozen exists?

    • @nickchapsas
      @nickchapsas  Před rokem +1

      It's the price you have to pay for having an immutable collection with the option to return new mutaed state as a new immutable collection

  • @cn-ml
    @cn-ml Před rokem

    Why is the immutablehashset contains method slower than the mutable one? Shouldn't they be the same, because contains does not mutate the collection? I'm thinking that the immutable one should be faster, but never slower

    • @nickchapsas
      @nickchapsas  Před rokem

      Every immutable collection is slower than it’s mutable counterpart because it is using AVL tree to store the data, making operations O(log n)

  • @BinaryNexus
    @BinaryNexus Před rokem

    .net 8? Did I sleep a full year? lol

  • @0shii
    @0shii Před rokem

    With all of these options using more memory than their standard counterparts and the creation speed of the frozen collections being so slow that you need to make tens of thousands of calls to benefit from the difference in lookup speed, I question the value of them at this stage of the development.
    I would be inclined to just construct a shim around the standard collections which prevents addition / removal if immutability was a concern and I didn't think I could trust the callers of my methods to not manipulate the collection.
    Almost regardless of what you do there will be some way for a caller to mutate the collection (e.g. reflection or the method shown here), so there's no real stopping a malicious caller, but an interface that removes the addition / removal methods or a derived class / shim that just throws an exception when they're used should suffice to prevent any accidental modification.

  • @Denmaverick39
    @Denmaverick39 Před rokem

    haha this might be an entry to the unsafe coding

  • @Dimencia
    @Dimencia Před rokem

    What I don't understand is ... why can't that mutability be exposed? I'm sure performance is the same before or after you mutate, but it's just one extension method away, and if the class weren't labeled as completely immutable, it can be useful and expected. It's still fixed-length and the keys are immutable, but there's no reason to prevent you from changing the values (unless you want it to)

  • @notsingular
    @notsingular Před rokem

    Don’t try this at home, at work, not a problem 😁

  • @Bankoru
    @Bankoru Před rokem +2

    Really confusing naming conventions since frozen is exactly what you would expect from Immutable collections

    • @nickchapsas
      @nickchapsas  Před rokem +2

      FrozenSets exist in Python so they probably used that naming

    • @Bankoru
      @Bankoru Před rokem

      @@nickchapsas Ah makes sense

  • @Zatarra48
    @Zatarra48 Před rokem

    I am so confused. Why is the immutableHastSet slower then the Hashset? Why isnt it just the same HashSet-Code where Methods like add and remove either throw an error or return a new one?
    //edit: Ok it is a design decision right? Instead of making it so and to the add and remove via extension they made the type itself do it and therefore rely on a tree.

    • @nickchapsas
      @nickchapsas  Před rokem +1

      Yeah they are are using an AVL tree because of the and and remove operations. That makes them efficient because you don't have to rebuild the whole tree but it does mean that lookups are O(log n)

  • @Plug1ndk
    @Plug1ndk Před rokem

    You forgot to mark NSFW :-)

  • @darioabbece3948
    @darioabbece3948 Před rokem

    I do think they added this because they reckon that ImmutableCollections weren't such a smart idea

    • @agsystems8220
      @agsystems8220 Před rokem +4

      Immutable collections are there to support functional patterns. Entirely different use case.

  • @martinshields7122
    @martinshields7122 Před rokem

    Sounds like frozen is what the immutable one is supposed to be but they can't change because it will be a breaking change

  • @pauldbentley
    @pauldbentley Před rokem

    ReadOnly, Immutable, and now Frozen. Feels like a bit of a mess and very confusing. Maybe soon we will have a ReadOnlyImmutableFrozenDictionary 😅

  • @dimitrishadrin
    @dimitrishadrin Před rokem +1

    Thanks for the video.
    It would be better if Microsoft combined these two concepts.
    Immutable collections should be actually immutable like frozen in .net 8. And if there is a case where an immutable collection should be mutated, it should support the same concept of creation mutated collection as a new instance via extension, decorator or ctor, etc.
    In my opinion it would be cleaner API.

  • @phizc
    @phizc Před rokem

    I'm not a huge fan of the names - frozen sounds like it's temporary.
    I can see a use case for a dictionary where you can't add or remove keys, but where you can look up and change the values extremely quickly.
    Making things completely readonly is almost impossible. You could do it with "native" memory and VirtualProtect to set the memory region to read only, but short of that you can even change the content of a string if you really wanted to. If that string was e.g. a key in a dictionary things would break since the hash value wouldn't change etc.
    Even setting the memory to read only wouldn't completely prevent change, unless there's a way to tell the OS to not allow any further permission changes on the memory.