Adding a BETTER way to loop in C#

Sdílet
Vložit
  • čas přidán 16. 10. 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 the secret extensibility points of C#, which will allow us to bring an AWESOME feature from Kotlin into the language. Not only we will make it work as if it was an official C# feature but we will also make sure it is really performant and fast.
    Workshops
    dotnetdays | 20 - 22 Oct | bit.ly/dotnetdays2022workshop
    NDC Minnesota | 15 - 18 Nov | bit.ly/ndcminnesota2022workshop
    NDC London | 23-27 January 2023 | bit.ly/ndclondon2023
    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 • 303

  • @nickchapsas
    @nickchapsas  Před rokem +72

    A couple of things I didn't cover in the video. Firsly if you are actually going to use this, make sure you also add an analyzer to warn or error on inappropriate usecases. Also, if you wanna support descending ranges for example foreach(var i in 10..5) you'd need to add a different check in the constructor and MoveNext() to support descending iteration.

    • @nanvlad
      @nanvlad Před rokem +6

      You also need to implement Reset() method to make an iteration variable reusable

    • @maunguyenvan9296
      @maunguyenvan9296 Před rokem

      how do you implement for loop with custom step like:
      for ( int i=0; i

    • @vincentjacquet2927
      @vincentjacquet2927 Před rokem +8

      @@nanvlad You are theorically right. Unfortunately Microsoft gave up on this a while ago, as the Reset method of enumerator generated with yield throw NotSupportedException. Therefore you cannot rely on Reset unless you known which enumerator you are dealing with and how it is implemented.

    • @kamyker
      @kamyker Před rokem +5

      More importantly ref struct won't work in async code. I wonder how slow would be class with pooling.
      #Edit just change it to plain struct. Even .net List uses non-ref struct Enumerator so shouldn't matter for performance.

    • @Grimlock1979
      @Grimlock1979 Před rokem +13

      @@maunguyenvan9296 You can make an extension method on ValueTuple. So you can say: "foreach (var i in (0..50, 2))".
      Or you can extend ValueTuple, based on how ranges in Haskell work: they are of the form "[first, second .. last]". So that would be: "foreach (var i in (0, 2..50))"

  • @reecenoone3113
    @reecenoone3113 Před rokem +115

    This is why coding is a form of art… I knew about all these features but never considered putting them together in this way

    • @looperx
      @looperx Před rokem +8

      In your defense the usability of a range with for loops is not something you should have to hack in yourself. It should come with the language.

    • @EddieVillamor
      @EddieVillamor Před rokem +3

      It sure can be such a form of art, especially when you get into clean coding and trying to come up with ways to make the simplest syntax

    • @kylekeenan3485
      @kylekeenan3485 Před rokem +3

      If we all coded in our own forms of "Art" we would be back to the 90's/00's with terrible code rampant everywhere that noone understands and doesn't want to touch.

    • @EddieVillamor
      @EddieVillamor Před rokem

      @@kylekeenan3485 or you could end up with a github community with guidelines and standards that everyone follows like we have now. A form of art that people are influenced by and mimic.
      Art is influenced by each other, not every single person will want uniqueness on every single thing we create. I mean is it not true that while poetry and drawings are limitless, there's really only a select number of ways to create things that make for a better product than other techniques that give the same result. So as with coding, and as it is today, everyone can create code in whatever way they choose, but because it's so artsy, you can write several ways to make the same hello world application, but do we? Nope, we always use the same examples everywhere with the same standards, etc, and we naturally, and typically, want to use the simplest path with the cleanest looking code. So it's just a matter of exposing the art for others to be influenced by.

    • @kylekeenan3485
      @kylekeenan3485 Před rokem

      @@EddieVillamor Your talking about a dream. We see people moaning about how agile doesn't help and that is clearly documented and has standards, guidelines, training courses galore. If people under those circumstances can't get it right, then following some unique (art) coding style will be a nightmare. Coding in your own unique style that's unusual and different to standard practices will just cause time delays and tech debt. It could in theory with proper guidance and teaching become useful as you stated but it never does. If people want to deviate from standard practices then it's probably best to keep it in their own personal projects. If you do discover something generally better then write a book 😁.

  • @DryBones111
    @DryBones111 Před rokem +33

    As much as I love the simplicity of the syntax, unless it's implemented in the language itself, I wouldn't use it because it is unexpected. Anyone else coming to the codebase would be confused seeing that and not finding anything about it in the official docs.
    In a similar vein, I love playing with the implicit operators but they have the downside of hiding what's really happening underneath. You've got to weigh up the benefit with the cost of abstraction as with anything.

  • @11r3start11
    @11r3start11 Před rokem +116

    Its a cool feature that could make DSL even more represented in code. But "unexpected" C# code should be maintained, documented and is not junior-friendly.

    •  Před rokem +19

      Agreed. It is a bit too clever and the benefits are IMHO not that big.

    • @neociber24
      @neociber24 Před rokem +17

      This is a feature that should be baked into C#, I don't really agree with add extension methods for this.
      I don't get why ranges don't just return an enumerator

    • @NoGamer256
      @NoGamer256 Před rokem +7

      @@fredriksjoborg7021 Let's just get back to C# 5 then it is even more simple.

    • @phizc
      @phizc Před rokem

      @@neociber24 re: why ranges doesn't return an enumerator
      ranges can't always produce a start/end value unless it's provided with a length. It's Start and End properties are Index, not int.
      E.g. "0..", anything with the hat symbol.. on my phone so I don't know how to type it... the one above the a: â

    • @DryBones111
      @DryBones111 Před rokem

      @@NoGamer256 The difference is that official language features are extensively documented and can be found in any codebase. Custom language extensions are a new thing that needs to be learned. If it provides enough value, it can be worth it. Is changing "Enumerable.Range" into ".." worth it? That's up to you.

  • @KevinInPhoenix
    @KevinInPhoenix Před rokem +60

    It never ceases to amaze me how much effort people will spend to save a tiny bit of effort.

    • @42069_
      @42069_ Před rokem +1

      hahahahahhaahaa

    • @cheebadigga4092
      @cheebadigga4092 Před rokem +1

      well this is just an example, you could also provide enumerators for your own types and make them behave this way if appropriate in that situation

    • @billy65bob
      @billy65bob Před rokem

      This is what we call a programmer move :^)

    • @Dimich1993
      @Dimich1993 Před rokem

      true

  • @ignaziomessina69
    @ignaziomessina69 Před rokem +2

    I definitely want this language feature in future version of C# natively! For me it's really fast to write and clear to read

  • @Vennotius
    @Vennotius Před rokem +21

    Having come from Python to C#, I could see myself really liking this near the beginning of my C# path. But now I have gotten used to how C# works and looks.
    This is nevertheless interesting from an educational point. And it is a good reminder that one can build your own things to meet your needs or just to make things behave more to your taste.

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

    I've used enumerators before, but never had it implemented as a feature of the code itself. Genius!

  • @thinker2273
    @thinker2273 Před rokem +5

    If/when the Roles & Extensions proposal is implement into C#, you'll be able to not only make anything enumerable, but also implement IEnumerable for any type, so you'd literally be able to use Linq on ranges. You're also able to do the same for GetAwaiter which is what makes the await operator function, and you can even make types besides Task/ and ValueTask/ into acceptable return types for async methods. Extension methods (and hopefully soon Roles & Extensions) is truly one of the best features of C#.

    • @NoGamer256
      @NoGamer256 Před rokem

      They started exploring in 2017. I just don't have much hope. There is crowd of people saying that C# is getting too complex and people don't know what to use anymore. I think they listen to them.

  • @R.Daneel
    @R.Daneel Před rokem +5

    I expect this to enter the language. It also feels like its exclusion is an oversight (which, of course, it's not). The .. format is just so elegant and self-explanatory.

  • @dimasveliz6745
    @dimasveliz6745 Před rokem +11

    very interesting. Hopefully will be built in. Having this custom classes all around and having to add them as a reference to each project for Syntactic sugar purposes is a tremendously big deal. Thanks for sharing though!

  • @TheSilent333
    @TheSilent333 Před rokem

    You continue to blow my mind with these little pearls. Thanks Nick!

  • @Jacobhay09
    @Jacobhay09 Před rokem +12

    I love your content. I am 100% self-trought and learned on the job where I work. So I don't get exposed to things as much I as I would like. But your small bite-sized videos keep me thinking about new ways to do things. I am able to take these back to some of our older projects and be a fresh set of eyes on them. Thanks again! I am in MN but due to budget cuts, I lost the funds set aside for training and events this year. Maybe I will be able to check you out next time you are in the citites. Keep up the amazing work!

    • @LittleRainGames
      @LittleRainGames Před rokem +1

      Best way is to start coding at home, and to just try new things and read.
      Eventually you come across stuff like this.

  • @kylekeenan3485
    @kylekeenan3485 Před rokem +2

    It's a nice idea if it was implemented into C# for all to use, but not as a random thing added to a project. Last thing we need is rewriting the wheel because it looks slightly nicer. This sort of behaviour is what leads to technical debt over a long period of time.

  • @nekuskus5218
    @nekuskus5218 Před rokem

    A super interesting way of using extensions! Thanks a lot for this

  • @Spherous
    @Spherous Před rokem

    Omg yesss! This is a feature I very much miss from Rust when using C#. Thanks!

  • @KeithOlson
    @KeithOlson Před rokem

    I learned a trick in the '80s that I still use today: instead of using 'i'/'j'/etc. for your loops, use 'ii'/'jj'/etc. That way, any time you come across a double letter you *know* that it is a loop variable.

  • @anaselhassani2545
    @anaselhassani2545 Před rokem

    Worked , thanks a lot!

  • @owns3
    @owns3 Před rokem

    power of extensions - love it

  • @alisonhj
    @alisonhj Před rokem

    I would use it, very elegant, congrats!

  • @Galakyllz
    @Galakyllz Před rokem

    I didn't even think about creating useful enumerators based on native types. Great video, thanks.

  • @gui.ferreira
    @gui.ferreira Před rokem

    That is really a clever idea Nick! Well done. 👏

  • @figloalds
    @figloalds Před rokem +27

    6:16 I don't see any problem in going to infinity since it's an Enumerator, the user code can break out of it using some other condition, that's the user-code responsibility, it does make sense.
    Now if start is from start then maybe count from the end down would make more sense

    • @nickchapsas
      @nickchapsas  Před rokem +6

      It actually won't go into infinity the way its implemented. It will just instantly exit the loop

    • @ronsijm
      @ronsijm Před rokem +11

      @@nickchapsas I think what @Felype Rennan means is that it could make sense to make it loop infinity if no end is defined. You'd just have to write something like `foreach (var i in (5..).Where(x => x < 100))` so that a linq extension eventually breaks the looping

    • @nickchapsas
      @nickchapsas  Před rokem +7

      @@ronsijm Oh I see. Yeah it might make sense, butthere is no infinity technically since ints have a max value, so you'd need special handling for a feature that doesn't really make sense to me from a language design standpoint. It's why Kotlin itself doesn't allow it too

    • @AConversationOn
      @AConversationOn Před rokem +2

      @@nickchapsas An infinite iterator itself makes sense, so here you /could/ interpret `10..` as `10 forever`: 10,10,10...

    • @figloalds
      @figloalds Před rokem +5

      ​@@nickchapsas true. I would implement " is from end" as "Int32.MaxValue" and call it a day, because in practice no indexed loop realistically goes to infinity
      If the programmer needs something infinite then they'd be using while(true) instead, it's even faster to write and easier to read than foreach(var i in x..)
      At the same time I think it's useful for if you need (0..).Where(Predicate).Take(200)
      Where limiting the range to 200 first then applying a filter would produce an incorrect result
      This is more convenient than requiring the user code to explicitly say (0..Int32.MaxValue).Where....
      IMO

  • @Denominus
    @Denominus Před rokem +3

    Fun side note. C# actually has quite a few of these "magic methods" that you can implement yourself. The LINQ query syntax is full of them, like being able to use the "from x in y select..." syntax on any type if you add a Select method with the correct signature to that type.
    I don't normally recommend it because its quite obscure and confusing to most people but its nice to know how the internals of some of these language features work.

    • @DryBones111
      @DryBones111 Před rokem +1

      Your specific example is pretty useful for implementing monadic code with an imperative syntax. I do like it, and it has its merits.

  • @vuquy711
    @vuquy711 Před rokem

    Awesome, Nick. I really love your videos!

  • @maskettaman1488
    @maskettaman1488 Před rokem +14

    Not a fan of this feature/syntax, but still super cool to see how you'd go about implementing it. Not something I had thought of but can definitely see using in other ways in the future

  • @Mazur_Family_Travel
    @Mazur_Family_Travel Před rokem

    I even haven’t known about syntax sugar. Nice videos, Nick! Great performance and work you are doing on your channel, thanks!

  • @KazLA
    @KazLA Před rokem

    thanks 🙏 Nick!

  • @Kommentierer
    @Kommentierer Před rokem +1

    This is actually super cool. Greetings from kotlin, every language has its nice feature we miss elsewhere.

  • @josephizang6187
    @josephizang6187 Před rokem

    OMG, Nick this is awesome. Thank you.

  • @parkercrofts6210
    @parkercrofts6210 Před rokem

    Wow thank you so much that really helped

  • @carldaniel6510
    @carldaniel6510 Před rokem +1

    Neat truck! I will absolutely use this.

  • @alirezanet
    @alirezanet Před rokem +3

    Great trick! I think we should open an issue in c# repo to support this internally, would be great feature

  • @TheMAZZTer
    @TheMAZZTer Před rokem +2

    Cool, though I wouldn't put a GetEnumerator on int. That seems a recipe for subtle bugs if you intend to iterate through an IEnumerable but accidentally grab a single int first. Normally you'd get a compiler error. So definitely should be careful with implied casts and similar tools like this.
    Plus if someone else looks at this code... for (var i in 10) ... they're not going to know wtf that is or why it even works. It is difficult to find the extension powering that. At least with the Range they can search the code for uses of the Range type to find it.
    Pretty cool but I find with foreach loops I don't tend to use normal for loops much. Even when I need the index or to put that index into a separate array, I can use LINQ .Select or .Zip to do that in a foreach (yes probably not efficient, my philosophy is to write nice code and only come back later if there's a performance need). That said I do avoid for because of the verboseness as you said so this does look tempting. Iterating over objects in a collection is usually what I am really wanting in most loops though.

  • @alfredoquintanalopez2265

    Great!!! I will use it.

  • @ziaulhasanhamim3931
    @ziaulhasanhamim3931 Před rokem +6

    If ref structs are used for enumerators foreach loops can't be used in async methods.

  • @Kingside88
    @Kingside88 Před rokem +3

    Yes I like it and would love to see it in C# itself

  • @matthewsheeran
    @matthewsheeran Před rokem +1

    Beautiful powerful C# that make it feel - almost - like Python! Great video Nick thankyou!!

  • @ermancetn
    @ermancetn Před rokem

    Probably i will not use this technique, but i liked the way how you elegantly implemented it.

  • @maaadkat
    @maaadkat Před rokem

    Supporting descending without affecting performance is tough. You don't want an if statement in the middle of MoveNext. Branch Prediction might sort it out, but the generated ASM contains the cmp every time so there's no compiler optimisation breaking the method into two and preselecting which to use. I didn't run a performance test, though, so it might be OK.
    I tried swapping behaviours in with a Func behind MoveNext() which pointed to named methods (lambdas in structs can't reference instance members), but while the enumerator worked in that it iterated the right number of times, the value in the foreach loop remained 0 which is pretty odd. As if either the value was cached, or copied and different copies used inside and outside the enumerator.
    What did work was creating an interface with Current and MoveNext, and a static method (yes, interfaces can have static methods!) to get one of two specific implementations (as structs, not ref structs). Structs implementing interfaces can have performance implications with boxing if the structs are cast to and from the interface, but the fact that foreach loops only require Current and MoveNext to exist, and don't depend on IEnumerator, indicates that it's unlikely to be an issue.

  • @pritishranjan
    @pritishranjan Před rokem +2

    This is the real beauty of C#. Its not coding mate...it's Art. 👏

  • @renatogolia211
    @renatogolia211 Před rokem +2

    Is there any specific advantage on not implementing IEnumerator in the example? I understand the advantages of duck typing for types that we don't own (like the methods extending Range and Index) but whenever possible I'd still prefer using interfaces when available.
    Also, this is something I'd like MS added to the BCL as it makes very much sense to iterate on a range.

  • @ristopaasivirta9770
    @ristopaasivirta9770 Před rokem +1

    This looks like something Jon Skeet would have done, I love it :D

  • @joost00719
    @joost00719 Před rokem

    I used this feature to be able to await a cancellation token. Awesome stuff, feels like magic :D

  • @chefbennyj
    @chefbennyj Před rokem

    Oh! that is just the best! Yes, let's see some numbers. Very cool

  • @soverain
    @soverain Před rokem

    Very interesting! I'm sure there is more to do with this!

  • @hudsentech8663
    @hudsentech8663 Před rokem

    Tnx!

  • @adassko6091
    @adassko6091 Před rokem +2

    Loop like foreach (var i in 0..) actually may make sense in combination with break and yield. That's actually a cool way to write a loop from zero to "infinity" with a counter

    • @krccmsitp2884
      @krccmsitp2884 Před rokem

      I'd suggest "infinity" or "from end" would be int.MaxValue then.

  • @WillFuqua1987
    @WillFuqua1987 Před rokem

    A similarly cool "language hack" that's been possible for ages is using the "Add" extension method to implement the JavaScript and Kotlin "spread" behavior for lists, to support syntax like: new List { "a", "b", nestedListOfString };

  • @davidnguyen9065
    @davidnguyen9065 Před rokem

    Most of your us are still learning the crust of .NET, figuring out the ins and outs and the basics. But here u r extending the entire framework and diving deep into its internal source code and showing us how to rewrite parts of .NET to perform better. This is just a no-go zone for most of us

  • @EwertonSilveiraAuckland

    Amazing.. mind blowing ❤👌🎉

  • @sealsharp
    @sealsharp Před rokem

    Thats pretty sweet!

  • @ZeroSleap
    @ZeroSleap Před rokem

    I am a stickler for having the rigid syntax of a for loop usually.But i am in love with this extension,seriously thinking of adding it to my projects.But the only concern would be for other people to understand or even run my code if they dont have this extension method.

  • @antonmartyniuk
    @antonmartyniuk Před rokem

    Looks interesting!

  • @dcuccia
    @dcuccia Před rokem

    I've wanted more duck typing for numerics for ages - this is an awesome capability. Replacing Enumerable.Range(...) will go a long way to having functional code look a lot more functional, and quite competitive with Python, Matlab and Ruby for expressiveness. And with the new static abstract interfaces, I'm actually looking forward to building custom Span iterators over large multi-dimensional datasets (across different axes). Thank you Nick!!

  • @beriu3512
    @beriu3512 Před rokem

    This is the type of thing that really makes me interested in C#

  • @ChristopherSalisburySalz

    I would use it in a personal project for sure. I'm not sure about work. Probably be fine for work because we create extension methods for things from time to time so it's really not any different than that.

  • @CraigBoland
    @CraigBoland Před rokem +4

    I like the terse syntax and would use this. However, most of the looping in my applications is iterating over a collection, so 'foreach(var item in items)' is my typical pattern.

  • @HalasterBlackmantle
    @HalasterBlackmantle Před rokem

    I loved this kind of syntax in Python. So I would use this without a second thought in C#.

  • @grainfrizz
    @grainfrizz Před rokem

    This is so cool

  • @user-nh8vd4nv5t
    @user-nh8vd4nv5t Před rokem +5

    Reminds me of overflowing c++ code with macros where everything looks cool but you don't understand how it works anymore without reverse engineering them back to normal code

    • @reecenoone3113
      @reecenoone3113 Před rokem

      I’m always in two minds about macros. Easy refactoring, terrible readability

    • @NoGamer256
      @NoGamer256 Před rokem +2

      So in Kotlin it is cool cause you can't find out how it works easily. In C# it is bad cause you have to write it yourself. Makes sense.

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

      @@NoGamer256 Its cool for Kotlin because its Kotlin syntax, its bad for C# because its Kotlin syntax.

  • @0xfded
    @0xfded Před rokem +2

    Another slight drawback is Range does not support negative numbers, so you can't do -5..5 as you can in Kotlin. It should have been called IndexRange as it's designed to support index ranges rather than value ranges.
    Still a cool hack if you're ok with non-negative ranges.

    • @billy65bob
      @billy65bob Před rokem +2

      You actually can.
      e.g. foreach(var i in ^10..0) { } will go from -10 to 0.
      You'll need this version of the ref struct though.
      public ref struct RangeEnumerator
      {
      private int _current;
      private readonly int _end;
      private readonly bool _forward;
      public RangeEnumerator(Range range)
      {
      _current = range.Start.IsFromEnd ? -range.Start.Value : range.Start.Value;
      _end = range.End.IsFromEnd ? -range.End.Value : range.End.Value;
      _forward = _end >= _current;
      if (_forward) _current--;
      else _current++;
      }
      public readonly int Current => _current;
      public bool MoveNext() => _forward ? ((++_current) = _end);
      }

    • @0xfded
      @0xfded Před rokem

      @@billy65bob Thanks! I didn't think about the ^ operator. And that's some tight code, very impressive.

  • @yuGesreveR
    @yuGesreveR Před rokem +2

    Actually, this is the first time when I see, that the duck typing in foreach loops can be really useful. I've never thought about ranges in such a context. This is really an elegant approach👍

    • @BillieJoe512
      @BillieJoe512 Před rokem

      I never knew this was possible! I always thought a class needs to implement IEnumerable to be used in a foreach loop. as for the feature itself, I think I feel about it similar to Unity's coroutine System: I'm not sure if it is a perversion of existing features or just brilliantly elegant.

  • @filipweisser2634
    @filipweisser2634 Před rokem +2

    Note that in func programing you can see even x.. (to infinity lazy) and its valid use case where you can stop the loop in the inner implementation.

    • @DryBones111
      @DryBones111 Před rokem

      Although if its lazy, you're not really stopping a loop, you're just finished grabbing values from the iterator :)

  • @matsnord4092
    @matsnord4092 Před rokem

    I'm not a c# programmer, have been mostly working with perl, python, js and java. It feels like home for me.

  • @WillEhrendreich
    @WillEhrendreich Před rokem +2

    Nice, literally anything that's puts c# closer to f# is a win in my book.

    • @WillEhrendreich
      @WillEhrendreich Před rokem

      @@MiningForPies oh I agree, wholeheartedly, but the more c# looks and acts f#-ish, the more people will see that f# isn't intimidating, and maybe they will switch to the best dotnet language after that..

    • @Erlisch1337
      @Erlisch1337 Před rokem

      @@WillEhrendreich they already switched to C#....

  • @diadetediotedio6918
    @diadetediotedio6918 Před rokem +1

    I really like this syntax. I had seen for some time that it was possible to make conventional arrays support destructuring through extension methods as well (to support a more functional way of dealing with arrays, without having to use Spans [which work very well for that too]), it's interesting see the breadth that you can take this.

  • @Galakyllz
    @Galakyllz Před rokem

    I can imagine making extension methods for tuples of specific types.
    ex: Tuple contains my repository class (which implements a generic "get all" method) and the total number of records to return
    ex: Tuple contains my API endpoint (Uri) and JSON data (Object) which returns an array of JSON objects serialized to type T
    That said, it's probably best to just create custom classes for each of these and implement IEnumerable, but the possibilities are interesting to think about.

  • @stratosmav7993
    @stratosmav7993 Před rokem

    Nice!!!

  • @PhodexGames
    @PhodexGames Před rokem

    I didnt knew x..y was an actual operator in C#. Well done.

  • @davidjsutherland
    @davidjsutherland Před rokem

    That was fun.

  • @jonathanperis3600
    @jonathanperis3600 Před rokem +2

    Please add a PR for this be included on C# 12!

  • @AndrewJonkers
    @AndrewJonkers Před rokem +1

    I would love this usage to be available, even as a C# feature. HOWEVER a big caveat for C#: Implementing anything other than what the current Range operator allows will just confuse code intent. That is start..end must be inclusive of start and exclusive of end. So 0..3 has indexes 0,1,2. This is just an implicit unchangeable fact of life for C#.

  • @dennycrane2938
    @dennycrane2938 Před rokem

    Yeah you can do this type of duck typing to create custom Task classes too, to mimic how Java/Android used to do them. Same way middleware works in asp.

  • @LukeVilent
    @LukeVilent Před rokem

    By necessity, I work on python for the last few years, and I'm kinda used to python loops and find them elegant. But I see languages converge on something that is just easy to write and read, and it's lovely to see C#, my most loved language, to go yet one more step in this direction.

  • @jeanmartin3256
    @jeanmartin3256 Před rokem

    Nice, I just like to know in which version it's supported ! Thanks

  • @jonasex3001
    @jonasex3001 Před rokem

    It could make sense to use till the end, the user can always exit the loop on whatever condition

  • @KerchumA222
    @KerchumA222 Před rokem

    Hey Nick, I would be interested to see if you know of any use cases for the other duck typings in c# (await for example).

  • @2947jasmine
    @2947jasmine Před rokem

    To avoid the conventional for loop, we are creating an extensions class & getenumerator method. Thus we are making our for loop more consize and readable/presentable. Please let me know what other benefits can we get through this method. I am learning, please correct me if I got this wrong

  • @lyrion0815
    @lyrion0815 Před rokem

    Thats an creative way of implementing it. I somewhere saw how you can implement an extension that makes it possible to write "await TimeSpan.FromSeconds(3)" or even "await 3" by making an extension method on int like this
    public static TaskAwaiter GetAwaiter(this int millis)
    => return Task.Delay(millis*1000).GetAwaiter();

  • @charles_kuperus
    @charles_kuperus Před rokem

    Wow. This is damn awesome.

  • @RomainLagrange1
    @RomainLagrange1 Před rokem +2

    Why MS didn't make Range enumerable in the first place ?

  • @Rovsau
    @Rovsau Před rokem

    I think testing would need to be done with multiple types and scenarios, to see if and when it makes sense to use it.
    If it is actually overall performant on large collections, it could at least be used to write faster and more readable code at the same time.
    Though, if a beginner adopts this, I imagine it may be difficult to receive help debugging.
    If readability is the primary goal, is there a way to make a Loop() method for all types of collections?

  • @CambleDCS
    @CambleDCS Před rokem

    Big fan of extension methods in general and this is really nice!

  • @CarstenFuehrmann
    @CarstenFuehrmann Před rokem

    Very interesting, in particular the duck typing part. One downside here is that we still can't call LINQ methods on ranges.

  • @void_star_void
    @void_star_void Před rokem

    Hey Nick thanks for the video. You also coding in kotlin or just interested in other languages 😁

  • @TheSimonDavidson
    @TheSimonDavidson Před rokem +5

    I do really like the syntax but would you have any concern about a fresh developer coming onto a project that implements this? If the extensions do have custom implementations that may not be obvious, it would be very easy for a new developer to miss that for something that should just be a basic loop.

    • @nickchapsas
      @nickchapsas  Před rokem +8

      The same concern I have when senior developers get exposed to new C# features

    • @TheSimonDavidson
      @TheSimonDavidson Před rokem +1

      I think my concern is more that the implementation is in the extension. Depending on who has written it, it could be inclusive or exclusive. I still consider myself a relatively new developer and while this syntax is easily readable, hiding the actual mechanics of it away in an extension class could cause confusion down the line if they then try to use it elsewhere. I guess it's making sure there is decent onboarding to new devs to show them, this ISN'T standard functionality, this is how it works in OUR project.

  • @SoumeshRanger111
    @SoumeshRanger111 Před rokem

    You're the most prominent C# instructor on CZcams.

  • @zORg_alex
    @zORg_alex Před rokem

    Awesome. Not sure though if unity supports ranges.

  • @xlerb2286
    @xlerb2286 Před rokem

    I'd perhaps use it in code I owned if I had a lot of for() loops I was dealing with. But I'd be cautious about using it in a team setting. The team would have to agree that it was an extension with a value that exceeded the potential cost of requiring the knowledge that this extension was present, how it worked, and any limitations the implementation may have. For example are the ranges inclusive or exclusive, are descending ranges supported, does it just work with ints or can you use enums, etc. Is usage of this required, recommended, or developer preference? Who maintains that code and how is the team notified if there are any changes made to it that affect behavior? So another words, the same as any other component you consider taking on as a dependency 🙂

  • @QwDragon
    @QwDragon Před rokem +6

    It's very cool, but I think that the normal loop seems better.

  • @jebarcha
    @jebarcha Před rokem

    Hi. Is there a coupon code for your courses? Thanks.

  • @stevepettifer4896
    @stevepettifer4896 Před rokem

    Elegant? Yes, and a very cool experiment. But would I use it? Probably not. It doesn't really save anything except a few keystrokes and unless your loops routinely deal with larger ranges then there is a performance penalty, albeit a very small one which may or may not add up to something more significant (YMMV of course). And even if you use larger ranges all the time, it's performance neutral and still confers no tangible benefit. Someone else made the point about it being 'unexpected' code and needing maintaining and documenting, and not being junior friendly and I think those are very valid and underrated points. If you are prepared to invest that time and effort and don't mind the extra cognitive load for juniors, albeit a small one but again these things add up, then I guess you could go for it for the sake of elegance but it feels like this is better held up as a practical explanation/example of duck typing than something to use generally.

  • @RamirodeSouza
    @RamirodeSouza Před rokem

    Is the WHILE loop still used/useful? Between the FOR and FOREACH it feels kind of dead.

  • @doge9203
    @doge9203 Před rokem

    bruh, this is magic

  • @Michal_Peterka
    @Michal_Peterka Před rokem

    Is it possible to implement "=>" for foreach loop?
    F.e.
    foreach(var element in elements) => element.doSomething();

  • @kvloover
    @kvloover Před rokem

    doing things like this is one of the funnest things to do in programming, but all my coworkers hate me when I do :D

  • @LeMustache
    @LeMustache Před rokem +10

    I wonder why ranges don't implement IEnumerable by default. Are they planning on adding that?

    • @lordicemaniac
      @lordicemaniac Před rokem

      but what would be increment?

    • @LeMustache
      @LeMustache Před rokem

      @@lordicemaniac I'm not sure what you're asking

    • @lordicemaniac
      @lordicemaniac Před rokem

      @@LeMustache range 1..10, should it increment by 1, 2, 5, 10?

    • @LeMustache
      @LeMustache Před rokem

      @@lordicemaniac I think it's pretty obvious I'm talking about an implementation that's very close to what Nick shows in this video

  • @vorontsovru270895
    @vorontsovru270895 Před rokem

    About six months ago I set the same goal =)
    My code came out a little worse, but it will do for an experiment =)
    To be honest, I somehow didn't think about ref struct then

  • @oriRelastwish
    @oriRelastwish Před rokem

    Code has have a bug if trying to loop from Minus Infinity since you're doing minus 1 on Start. IMO the incrementor should be after the MoveNext condition and change the