Why is C# Evolving This Way?

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
C# 12 is here, bringing a few fresh features. It's not a big release.  Still, it continues that functional line  of thinking that underpins the evolution   of the C# programming language  through the last 10 or 15 years.  Why functional design in C#? Many programmers still don't get that point.  So, stay with me, and I will try to clarify it. I will explain why there has been so much stress   on functional design and programming  in every single release of C#.  There will be no coding demo in this video. I want to explain the backing theory,   the knowledge every C# programmer must  know long before writing any C# code.  Let me tickle your imagination with a lovely  method utilizing expression-boded syntax.  That looks like a lambda expression. Oh, is this really a method?  This could also be a local  function - did you think of that?  That was a trick question. Now, using a similar syntax,   this time I assign a lambda to a  variable declared using the var keyword.  A lot of new stuff here that we  only got in the last few years.  The trick question: What is  the type of this variable, g?  Come on, try your luck.  Write your answer in the comment. I would like to hear your thinking.  What do you think, what is the  type of this variable, tell us!  I'm asking because, before C# 10,  this assignment would fail to compile.  Now it compiles fine. Well, these two lines of code show C# today.  Some will hate it. Some will love it.  And so, the question is: How did we  get here, how did C# become this?  And let me remind you that you can also  join the growing community on my Patreon   page where you can exchange thoughts about  demos, video courses and many other things.  Come over there and join us. Now the history of C#.  C# 12, in particular, has  brought primary constructors.  They make regular classes  start looking like records do.  That will tease your mind if you  didn't accept records so far.  There will be a lot of debate about primary  constructors in the upcoming months, I think.  And I also believe that this is not  their final form we are seeing now.  It will be an interesting period  before they become a mainstay in C#.  Back to the previous version, C# 11, that is where  we we got more versatile pattern expressions.  The list of supported pattern-matching  expressions in C# seems to know of no boundaries.  C# 10 has also brought some improvements there. It has also brought improved performance on   records by introducing record structs that  literally render common structs obsolete.  And that is when we also got a nice little feature  that passed under the radar, mostly: Lambda types.  All right, that relates to that  question I asked in the introduction.  What is the type of this variable, g? This variable has a so-called natural type now.  It will be the Func delegate type that  corresponds to the signature of the lambda   assigned to the var variable. That is a novelty in C#.  C# is becoming quite dynamic  when it comes to lambdas.  C# 9, oh that was a significant release. Besides improving generics with covariant   return types - do you know what that is? - we  also got init-only seters and, behold!, records.  Any functional model is  unimaginable without records.  They remove 90% of clog, of code, in large  portions of any functional domain model.  Do you use records in everyday coding? And don't tell me you're only using them as DTOs.  That's not their purpose! Do you use them for their intended purpose?  That is the question for you. Did you really adopt records?  OK, back in time, C# 8,  another giant leap forward.  That is when the nullable reference  types came into the picture.  Nullable references, or as I always pointed  out non-nullable references, that is the point,   their invert, their negation, non-nullable  references have brought an idea into many   programmers' heads that they might write  code in which everything is an object.  That was the new territory for  so many programmers of the time,   and even today, unfortunately. Thinking that you can write an   entire model where everything is an  object and there is not a single null.  That is also when pattern-matching expressions  started to attain the power we know today.  And, before that, C# 7 brought one improvement  that mostly came under the radar: spans.  They improved performance, they are very useful. Anyway, C# 6, it cleaned some of the   syntactic noise in common code with  null-conditional expressions and,   now think: expression-bodied methods. Well that is exactly when C# adopted a   mainstream functional coding expression-boded  methods, methods that look like lambdas.  Don't change things, make your classes immutable,  and implement methods that just return a value.  C# 5 brought async and await, and C#  4 got covariance and contravariance.  But only a few programmers at the time figured  that these features are actually helping write   functional code and make functional designs. They came after C# 3.  Well, that was a big leap forward because  it was a game-changer in the direction of   functional design, and C# never lost track  of that line, that functional design line.  We got extension methods, lambda expressions,  expression trees - all the prerequisites to LINQ,   which has forever changed the terrain  in .NET application development.  We should remember C# 2 as well, which introduced  generics, and - voila! - here is the big picture.  It shows what many programmers fail to see even  20 years after this process started, and that   is that the most of the new features added to C#  and .NET are deeply in their hearts functional.  They support functional  design and functional coding.  I have already mentioned LINQ, which  is a first-class functional library.  And another one coming with .NET  Core 1: immutable collections.  That is how .NET and C# went hand in hand to  improve the ecosystem, to build a new ecosystem,   in which we can successfully write applications,  business applications, that are mixing   object-oriented with functional design. Generics, they are a world in itself.  Every piece of functional design is generic. Generics must be your second nature   if you plan to be a successful C#  programmer, it is as simple as that.  Another large group is performance  upgrades that affect code.  But these remaining features in between,  they are the essence of the modern C#.  Extension methods and pattern-matching  expressions, those are the tools for   defining behavior in a functional model. And the rest, the rest is pure gold.  Know this and you know C#. These are the essential   features in functional domain modeling  and they are all supported by C# today.  I will skip generics and a few  other features in this video.  Each of those is a significant theme in its own  right and I just cannot cover them in this video.  I want to focus on this subset of features here  because not all features there are born equal.  This large group on the left is  what we use when defining data.  Think carefully, especially if you  are deeply entrenched in the old   object-oriented thinking style. We use these features to define   elementary data structures. These structures contain no   behavior but only model the data. Pattern-matching is another   important aspect of modern C#. You have seen that every recent version of C# has   got more and more of pattern-matching expressions. If you hate those cryptic little bastards, then   think again: you might be wrong in judging them. They will keep coming, more of them.  They won't stop. The rest is just   syntax that glues all this together. So, to draw a line under the last 15   years of C# evolution, this is the central theme  you see here: Separation of data and behavior.  But why? That separation is also the   central pillar of functional programming as well. It makes functional programming what it is.  And now, it is a native resident, the  first-class citizen of C# as well.  Here is why. It is because of   the way how we develop software today. We don't just create an, I don't know,   web application, with a SQL database under it. That time is long gone.  Today, we also develop other applications, other  services, potentially each having and owning its   own storage, using a different storage technology. But that, that means little.  There are also services that  don't even have storage.  They must talk to other services  and applications to get the data   before spitting out their own output. And more, there are third party APIs on   the Internet we will connect to. This picture shows the hidden   truth behind application development today. We write data in one shape, in one form, but   then read it and process it in many other forms. We should favor pattern matching when implementing   all those numerous mappings. Pattern-matching expressions are   highly readable compared to procedural mapping  code and they're also almost always easier to   write than the corresponding procedural code. They help us reduce development time but also   reduce the bug count by a large margin  compared to traditional coding styles.  No wonder that C# has been improving its pattern  matching support in every version I can remember.  Before farewell, let me show you  just a bit of a domain model I   have developed in some imaginary application. There's a whole bunch of immutable records here.  Could those be classes, traditional  classes with methods and the state in them?  Oh, wait a second! You didn't hear it all.  These data are not mine. Part of them came from deserializing   a response from another service. With that data I form a request   for yet another service which will  send me over the rest of the model.  Do you see what I'm trying  to tell you all the time?  The programming has changed and that  is why the C# language is changing,   not because somebody wants it that way. Most of the programming today is like: here's my   JSON, give me your JSON, thank for the JSON. How can you mutate the   data you didn't even create? How can you expect an object, an object that comes   with behavior, if that object would be, the class  of that object, would be developed by another   team, writing another service, which doesn't even  know that your service that consumes it exists?  Let alone, how could it understand  the business needs of your service?  That is the separation  between the data and behavior.  That is where extension methods, lambdas and  everything related to that come to the picture,   letting you define behavior specific  to your domain on the the data   structures that you got from the other domain. There are two ways for you from this point on.  You can stick to the old-fashioned  object-oriented, pure object-oriented design,   and hate it all the way through, suffer through  every line of code in modern applications.  Or you can adopt the functional mindset and  start enjoying C# 12 as it is, as a mixture   of object-oriented, functional,  and procedural coding and design,   all supported in one language and one platform. Now is the time for you to start coding, now   that you understand what language you're using. Subscribe to my channel and watch other videos.  Every other video but this one is a coding  demo on my channel, so start watching them.  Start from this demo, for example,  first, and enjoy using the latest C#.
Info
Channel: Zoran Horvat
Views: 20,644
Rating: undefined out of 5
Keywords: csharp, dotnet, programming, object-oriented programming, functional programming, c#, zoran, horvat, zoran horvat, c# programming, learn c#, c# tutorial, c# 12, lambda expressions, extension methods, generics, primary constructors, primary constructor, expression tree, record, records, record struct, record structs
Id: RfEbn9aXY-Y
Channel Id: undefined
Length: 15min 2sec (902 seconds)
Published: Thu Dec 07 2023
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.