The evolution of Pattern Matching in C# (from version 6 to 10)
Vložit
- čas přidán 19. 06. 2024
- Check out our open positions at Checkout.com here: bit.ly/NickChapsas02
Join me and let's build the future of payments!
Check out my courses: dometrain.com
Become a Patreon and get source code access: / nickchapsas
This video is sponsored by Checkout.com
Hello everybody I'm Nick and in this video I will show you how pattern matching was introduced in C# and how it has evolved from version 6 all the way to version 10. It is an amazing feature which can be really handy to prevent you having to write lengthy complicated clauses.
Timestamps
Intro - 0:00
I am hiring! - 0:47
C# 6 - 1:37
C# 7 - 3:03
C# 8 - 5:36
C# 9 - 9:31
C# 10 - 13:58
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
Check out our open positions at Checkout (dot) com here: bit.ly/NickChapsas02
Join me and let's build the future of payments!
Applied and really looking forward to multiplying each others' understanding. My personal goal is no less than improving humanity in itself. :)
It is becoming really hard to try other languages when your first and favorite language is giving you these awesome features. And .NET is in everything in everywhere.. Thank you Nick for showing this awesome feature
IMHO:
One thing that would definitely improve pattern matching is to *allow us to use other values besides constants.* As it stands, pattern matching literally forces us to use hard coded magic numbers if we want to do anything more than check types. The biggest reason I'm not using pattern matching as much as I'd love to is because way more often than not I need to match against VARIABLES, not constants. Right now you can't even do a switch expression on a Type object for crying out loud.
I know that one argument against matching against variables is that then the compiler wouldn't be able to (attempt to) guarantee static analysis, but I don't see a problem in not having it when using variables.
Seriously, variables in pattern matching have got to be the next step if people are to use it more.
Even in the context of something similar to the example, if you're branching based on some shape's geometrical properties in a real application, then you're gonna use, say, a float you got as a method argument, not magic numbers.
Even the functional languages where this originated from don’t support this. In F# you also have to do
match foo with
| { bar = quux } when quux = baz -> // do stuff
Same for Scala:
foo match {
case Bar(quux) if quux == bletch => // do stuff
}
This effectively does what you want, but this is effectively syntactic sugar for an “if”. And this also works in C# using “when”.
The argument against directly matching against variables is a very valid one, because a defensive style is the way to go today, even in primarily object-oriented languages, which also means everything should be considered immutable by default even if it is not in C#. I miss something like “readonly var a = 42;” - why is this possible for fields but not for local variables?
You have to adapt your coding style but immutability by default prevents some potentially nasty bugs.
@@20windfisch11 I don't think I quite understand what you mean. Could you please elaborate? I don't see the connection between immutability and being able to only use magic numbers while pattern matching objects.
@@petrusion2827 the relationship goes down to the compiler, in order to make sense of it and optimize it properly the values need to be readonly at compile time, so basically, constant
Elixir offers pattern matching like this, it also offers destructuring into new variables using pattern matching. You can also do function overloading using pattern matching.
However, it's not a strongly typed language, so that may be where the difference lies.
@@20windfisch11 I don't think this is even possible in statically typed languages (without it being syntactic sugar for an if/else). In Rust, i.e. a language with very strong guarantees) you can do this:
let num = Some(50);
let y = 10;
match num {
Some(x) if x < y => println!("less than {}: {}", y, x),
Some(x) => println!("{}", x),
None => (),
}
But again: This is syntactic sugar.
Even in Haskell, which is probably one of the more pure languages you can't do it and have to fall back to input guards, i.e.:
one = 1 :: Int
two = 2 :: Int
foo x
| x == one = True
| x == two = False
Boom! This blew my mind - loved this video. Please do more "evolution of ..." types of videos please. It really helps me understand what the new features are trying to accomplish.
12:36 I think adding parenthesis is also good to make it clear: c is (>= 'a' and = 'A' and
I'm not saying it's crazy. But, well, it is crazy! Amazing evolution! Thank you for share that, really a very nice job, another usefull tip, as always!
When I moved from VB6 to C# 15 years ago, I was shocked at how limited switch case was vs Select Case in the obsolete VB and VBA languages. Now C# has FINALLY surpassed Visual Basic in functionality and even readability with that extremely short syntax. Totally awesome, thank you for waking me up to this new future set!
Nick, excellent work. You really distilled pattern matching down into the most concise example I have seen to date. Very well explained and even taught me something new. Bravo!
I've watched a few of your videos before but this is the one that made me realise I need to subscribe, also going to recommend your channel to my colleagues.
Oh man can’t tell you how much I enjoy ur videos… ur the best tech content creator period…
I really appreciate you doing these videos. You're making us better coders 😀
I've recently stumbled upon your channel and so far I love it! Keep up the good work ♥
This is definitely useful for me.
I learn something from every video. Thanks for the great stuff you put up.
Είσαι τρομερός! great to see people like you sharing such valuable knowledge, keep up the good work!
Switch expressions with tuples under the right circumstances can make for crazy improvements to readability and conciseness. Awesome video.
And in the wrong circumstances will make your code a nightmare hellscape of fragmented incomplete edge cases
Value content! Thanks Nick Chapsas
Wow, that's amazing - thank you so much
Great explanation of Pattern matching. Thank you.
I've recently discovered the power of pattern matching when dealing with the returns of delegate functions. A delegate return could be void, an object, Task or Task. Using pattern matching I could determine if I could execute the task and return a result or just await it.
if (task is Task taskVoid) await taskVoid;
if (task is Task taskT) result = await taskT;
Perhaps Either would be better in this scenario?
@@SebGruch No, I know there is only a single return type as I defined the delegate. Plus I have a single function to execute the delegate which doesn't know about what it will be returning at he point it is invoked.
@@SebGruch yeah this sounds like very bad design, not your Either, that one is cool, but the multi type return
Great video with awesome explanation!
So nice, today I learned new stuff. Thanks
Great video,thank you very much!
2:05 Wait, there are example numbers besides 69 and 420? Who knew? 😛
1337 stands for LEET! Old gamer lingo man
@@orhanraufakdemir900 I'm more concerned by 5
Great channel, great video and great examples 👌🏾
Thanks dude! Awesome.
Great job!
Very nice examples and explanation 👍
Great summary of a feature I have not be using a lot, since in "oldskool software engineering" dynamic type checking is considered to be a bit of a code smell. But still, I can see the benefits of this "pattern matching", although the name is really confusing to me : I consider this to be "dynamic type matching", and e.g. regular expression matching is what I call "pattern matching".
My passion of c# is increasing thanks to your videos Nick 😉
Well said - thanks Nick!
Very nice! Though I was up to date. Was wrong :) learned something new. Thanks!
amazing. thanks
you do a good job. thank you
Really nice feature!
Love it, some good stuff there.
Good explanation
This is why I fall in love with C#
this is so good.
i love how changes makes c# more expressive.
Usually, great content!
This is so cool
Damn this is beautiful.
Oh lord this is going to make my code reviews look much cleaner at the very least
Fantastic video as always!
No open positions for Mexico, really sorry about that ☹ maybe one day...
at offset 12:40 important to note that "and pattern combinator has higher precedence than or" otherwise reader is left wondering if code is correct. Personally I prefer to explicitly include parens here to be 110% clear!
What interesting shape sizes you have there.
0:47 Sadly you're not hiring in Denmark. - Very good video as always. Thank you for sharing!
Really wish pattern matching could accept non-constant values. Can't use it almost anywhere because of that.
This so much. In a lot of real life projects, you are getting configurations from database instead of hardcoding them. So for instance in the pricing example shown, those discounts criteria range could partially be coming from db & then pattern matching won't accept it.
Ok, this really affects you if you are focused on doing functional programming with a lot of expressions. Code shown in the examples is harder to understand and change than “oldschool” if/else or switches. It has it purposes but it also has its limitations. Be vary with implementation, not everything is suitable everywhere. That aside great presentation and very interesting to watch! Kind regards.
Since they are advancing the pattern matching this much, I really wish they would introduce uniontypes etc. similar to typescript - it just seems it would be a good match, making it possible to e.g. return different types in a method, and the caller can then choose to handle this using pattern matching with type checks for the more limited amount of possible types (opposed to using e.g. object as return object).
Nice presentation! Property matching is a really cool feature, however they only work with const values. It won't work if you need to check against another object, at least not yet.
I found your typo "Nothing SPACIAL about this" in terms of geometry very charming :)
A sad caveat is that the evaluated values must be compile time constants, which in many (or most?) cases makes the feature simply useless. I mean, who really hard code parameters?
Exactly my thoughts
With code generators?
For a lot of these more "flavorful" features in other languages, I feel they're overly specific and cause more problems than they solve (looking at you, CSS). This seems fantastic, though. It's clear, concise, and customizable. Great video, thanks for the tips!
Started learning Haskell recently, so this is extremely interesting.
Do you know if there is a way to utilise a Predicate directly in the is {} syntax? Or do I absolutely have to make it in a separate condition(Ex: s is {} && myPredicate(s.Width))?
For example:
if (s is Rectangle { Width: Equals42 })
Where "Equals42", is a predicate that will receive a width in parameter and return true if it's 42, and false otherwise.
I knew the power of pattern matching in the switch expressions, but I had no idea you could do it in an if statement. That's awesome! Question though.... how could you (if at all possible) do pattern matching on a class property where you want to do .StartsWith or something like that? So I want to do something like - if (vehicle is Car { color: StartsWith("Blue") }), where color is a string. I know that's an oddball example, just trying to show what I'm asking :)
Thanks nick , I want the resource that contains this topics
C# pattern matching is getting there, I mostly use it nowadays to simplify multiple conditions. If/when union types arrive, domain modelling and logic in C# is going to look wildly different from today.
In the short term, I'd like to see them add support for expression statements so you can use switch expressions to execute different code paths. Either that or support for Unit (nothing) as a type, but that's much less likely.
Hi Nick, thanks for another interesting video. I am wondering, isn't dangerous to have two switch conditions about different properties of an object as both of the conditions can be true at the same time?
And what is happening here in the compiler code? Just nested if else statements?
Nice
When I first seen this back in C#8 I thought this was very powerful, but in practice there's not as many cases where I can use it in day-to-day code.
i really like how in your vids you go through the whole history. helps give needed perspective.
also, too bad we can't just type "area 100-200" instead of "area greater than 100 and less than 200"
There probably could be a notation to identify "between", but you would need identifiers for; inclusive of both, inclusive of lower, inclusive of higher, and exclusive of both.
Hmm now that there is System.Range, probably we should request the ability to use not only `Area: >=100` or `Area:
No worries, just make feedback to Microsoft and see the magic on the next version of C#
Perfect way to hide/forget the else paths, the "what happens if not" scenarios, which may missing from the requirements.
Can I write the block code inside a case of switch and return the same type as other cases? Or only one line? Thanks
Wow 🤩🤩🤩
Very useful video for an interview question: What new features have C# versions?
As long as the patterns being matched are consts / readonly, in a general sense will the runtime be faster than, say, the same amount of variables being checked with the classic if else statements?
what would you suggest to do in C# to have a small image and find it in a running program? like a screenshot image within any particular program for example
Do you happen to know if there are any available benchmarks for performance in using these types of complex matches in a switch? Most of my C# is done in Unity for games and tools, and most of the time when I see something neat, easy to use, and powerful (ex. Linq, etc) it ends up being something you absolutely do not want to use in a game loop due to allocations and often overall performance in general. Being that this is an actual built-in language feature and not just a convenience package, I am wondering if it would be more "safe" to use in situations where performance matters greatly?
What happens if two expressions in the switch statement are matched then which one will return? Does the order matter?
Pattern matching in C# is awesome, but one thing that really bugged me was that variables that were declared via pattern matching would not allow you to declare another variable of their name even when they went out of scope. For example if in some method i had an `if (a is Circle c) {...} and then `if (b is Circle c) {...}` it won't compile saying that `c` is already declared. But it not! The first `c` can only exist inside the scope of the first `if`. Swift handles this well. I hope C# would too
I was using some of this and I didn’t know that is called pattern matching. I was always wondering what is the recommended way: “shape != null” or “shape is not null”. At a moment I was debating with my coleague that we should use one or the other, to keep the same style everywhere. Now I understand that the second style is the new way and is ok to use it.
I have done a few test and both of them executed at same time, so u can use both without worrying or which one is better. But i still prefer the old school operator != bevause its easier to read haha
@@duytrananh2292 the new way is easier to read because you can read the code as a book you dont have to convert != operator in your brain into the not keyword
What is the shortcut command to change a string from "" to $"" while editing in it?
will it hit nullReferenceException? if yes, can we do a null conditional operator? if (randomShape is Rectangle { ShapeInShape?.Area: 100 }) ?
Nick some videos on AOP if possible...
We both have the same exact chair.
underrated feature
Underrated C# teacher! You're great bro, thanks, you've helped me a lot! haha.
Does it work with regular expressions?
Hi Nick, do you offer end of studies internship opportunities? can i apply as a software engineering student for a 6 month internship?
How does your Rider have c#10 and net6 support
Rider EAP is out with some support for C# and net 6
What's the reasoning for starting to use 'and' and 'or' in pattern matching like this instead of && and || ? Because it's an extension to linq syntax?
It doesn't have anything to do with LINQ. It's just a different operator
This went crazier each second. C# is a big deal!!
10:35 wish they code also introduce between operator on c# 10
I think there is it's ".." possibly?
Is last example from C# 10 with accesing area of nested object is null safe?
Depends on whether the reference is nullable or not
@@nickchapsas So your example will throw NRE cause you never initialized inner shape, but example with nested braces will not. Are ?. null-conditional operators allowed in pattern matching to avoid this?
@@iGexogen The C# 10 example has nullable reference types enabled so it assumes that the value will not be null. If there was an option for it to be null then it wouldn't be compiling
So, in a nutshell, C# just absorbs all the useful features of python, and making them even better. I wonder when we shall have (or do we already have?) variable typization, of the sort Union[TypeA, TypeB,...] of Python.
Hi Nick, wanna work with under your supervise.
it's nice to have options I guess, but I struggle to see how this is ever more readable than classic if-then-else syntax.
You say circle with area but then use the diameter instead 😅 otherwise great video like always, considering to sign up for Patreon
You can tell that I was sleeping during my geometry lessons
Isn't an example with checking for type is an example of beaking a OCP?
I wouldn't say so. If you have a unit test returns IActionResult and you wanna check if the result is OkObjectResult for some assertions purposes to access the underlying Value or StatusCode properties then that's a perfectly valid case, and there are hundrends other like it.
@@nickchapsas thanks for your attention. I didn't expect to get an answer from you personally)
A case you described is acceptable for type checks as far as I see.
But on the other hand I would like to warn beginners: if in production code you check for type and it has an impact on a code flow - this is a reason to reconsider a way you solving your problem.
I guess my point is next: language features(syntax su gar) do not allow breaking a clean coders practices. These features are to make your code cleaner and readable.
Thanks
I highly recommend all interested developers to interactively follow along in VS; it's really some very nice enhancements to the C# language that (among some of the more esoteric features they're adding) provide real production value imo.
Lol except hes usring rider, though either IDE should work fine. GG
2:56 couldn't I use if randomShap == circle ?
That just checks if the references are the same
C# is functional c++ and the best language ever made
Has he covered the performance of using ‘var vs int,string,double’ ?
Don't know if Nick did a video on this, but I do know the answer.
In C#, there is zero runtime performance cost to using var vs explicit typing, since the compiler automatically converts vars back to the strong types during compilation.
You could argue that var is slightly quicker to compile because there are fewer characters in var than string & double, meaning the compiler has to read fewer bytes from disk. But this is a very contrived scenario: in what circumstances would you care about compilation performance and source code file size?
That's your extra credit assignment.
@@shexec32 thanks for the reply, I was just curious ,I'm kind of new to c# ,coming from c++, I thought var would be the same as auto in c++.
I think sometimes this syntactic sugar makes the code less readable. Let's not get too close to Perl. :)
Why did they change it up and the "and" logical operator in the patterns is well "and" and not "&&" like im used to...
The only thing missing is being able to run expressions / statements from the pattern matching results itself.
A workaround is IIFEs. Create a Func and immediately invoke it.
The best feature of c# is that you usually able to use other language xD
if (randomShape is Circle {Radius: 10})
thats such a weird Syntax. Why isn't it the same as in switch?
if (randomShape is Circle cir when cir.Radius == 10)
Edit:
Ah I see - you can do the following:
if (randomShape is Circle cir && cir.Radius == 10})
I guess this isn't the default because it assigns a new- probably otherwise unused variable?
I use "is casting" all the time.
Thanks. Its nice, cool and useful in many cases, but some syntacs are a little ofuscated, so if you abuse using this, you could be writing no clean code. Clean code is one of the main objetives when you write code. You should not write code as a demostration to your partners of your clever mind. Your code should be clear and understable to everyone, and many times is not the compact way. Thanks.