The New Option and Result Types of C#
Summary
TLDRIn this video, Nick discusses the highly anticipated feature of C#, type unions, focusing on the introduction of the 'Result' and 'Option' types to the runtime. He explains their purpose, how they work in other languages, and their potential impact on C# development. Nick demonstrates their use through examples, comparing them to nullable types and exception handling. He emphasizes the benefits of these types for safer and more robust code, and encourages viewers to share their thoughts on this new feature.
Takeaways
- đ Nick introduces the concept of discriminated unions, also known as type unions, a highly requested feature in C#.
- đ Two native types, 'Result' and 'Option', are being introduced to the runtime, which are causing some confusion among developers.
- đĄ Nick explains that these types can be used to create safer and more robust code by explicitly handling different outcomes.
- đ He provides a demonstration using a simple console application to show how nullable types can be problematic and how 'Option' and 'Result' types can address these issues.
- đ The script mentions that using exceptions for flow control is considered bad practice and can be slow, which is where 'Result' types can improve performance.
- đ Nick shows how to refactor existing code to use 'Option' and 'Result' types, emphasizing the need to handle all possible outcomes.
- đ The video script also touches on the use of language extensions to add functional elements like 'Option' and 'Result' to the code base.
- đ Nick discusses the learning curve associated with adopting these new types and the benefits they bring to codebases in terms of safety and clarity.
- đ He highlights the importance of having a standardized approach to error handling and optional values across different libraries for better interoperability.
- đŁïž The script encourages viewers to share their thoughts on the new features and reminds them that Microsoft is considering community feedback for future updates.
- đ Nick promotes two new courses on DOM, Git, and GitHub Actions, authored by Scott Hanselman, offering advanced insights into these topics.
Q & A
What is the most requested feature of C# that Nick mentioned in the video?
-The most requested feature of C# mentioned by Nick is discriminated unions, which are more appropriately named type unions.
What are the two native types introduced in the runtime according to the proposal Nick discussed?
-The two native types introduced in the runtime are the result type and the option type.
What is the main purpose of the 'result' type in programming?
-The 'result' type is used to represent a value that can be either a success or an error, providing a way to handle different outcomes in a method call without using exceptions for flow control.
What does the 'option' type represent in programming?
-The 'option' type represents a value that can either be 'some' with a specific type of value, or 'none', indicating the absence of a value. It is used to avoid nullable types and enforce handling of both present and absent cases.
How does Nick demonstrate the use of 'option' and 'result' types in his sample console application?
-Nick demonstrates the use of 'option' and 'result' types by showing a 'getUser' method that returns an 'option' of 'user' and a 'createUser' method that returns a 'result' of 'user', handling both success and failure scenarios.
What is the issue with using exceptions for flow control in applications according to Nick?
-Using exceptions for flow control is considered a bad practice because exceptions are slow and can lead to less maintainable code. It is also a common criticism that it is not an efficient way to handle expected outcomes.
What is the advantage of using 'result' and 'option' types over nullable types?
-The advantage of using 'result' and 'option' types over nullable types is that they enforce handling of all possible outcomes (success, failure, or absence of value), leading to safer and more robust code.
Why does Nick believe that adding 'option' and 'result' types to the BCL (Base Class Library) is a net positive?
-Nick believes it's a net positive because it provides a common type that everyone will use, which can lead to a consolidation of libraries and NuGet packages, making the codebase more standardized and interoperable.
What is the current status of the 'option' and 'result' types in C# according to the video?
-As of the video, 'option' and 'result' types are available through NuGet packages and language extensions, but they are not yet part of the standard C# language or runtime.
What is the significance of the 'match' expression in the context of 'option' and 'result' types?
-The 'match' expression is used to handle the different cases of 'option' and 'result' types exhaustively. It allows for pattern matching to either handle the 'some' or 'none' case for 'option' types, and the 'success' or 'failure' case for 'result' types.
How does Nick suggest handling the potential null reference exception when using nullable types?
-Nick suggests handling the potential null reference exception by adding an if check to ensure the object is not null before accessing its properties, or by using 'option' and 'result' types which enforce handling of all cases.
Outlines
đ Introduction to Discriminated Unions and New Runtime Types
Nick introduces the concept of discriminated unions, also known as type unions, which are a highly requested feature in C#. He discusses the addition of two new native types, 'Result' and 'Option', to the runtime, which aim to address common programming challenges. Nick explains that these types are designed to improve code robustness and library consolidation. He also mentions the use of nullable types and the potential issues with null reference exceptions, setting the stage for a deeper exploration of these new types in the context of C# development.
đ Exploring Option and Result Types with Language Extensions
This section delves into the practical application of 'Option' and 'Result' types using language extensions. Nick demonstrates how to refactor existing code to leverage these types for safer and more explicit error handling. He contrasts this approach with traditional exception handling and nullable types, highlighting the benefits of having to explicitly handle all possible outcomes. The summary also touches on the performance implications of exceptions and the advantages of using 'Option' and 'Result' for a more functional style of programming.
đ Discussion on the Necessity and Future of Option and Result Types
Nick wraps up the video by discussing the rationale behind the introduction of 'Option' and 'Result' types in C#, despite the availability of similar constructs in .NET and language extensions. He emphasizes the importance of standardization and interoperability between libraries. The summary also includes a call to action for viewers to share their thoughts on the new feature and an invitation for feedback, noting that Microsoft is actively considering community input for the development of these types in C#.
Mindmap
Keywords
đĄDiscriminated Unions
đĄType Unions
đĄResult Type
đĄOption Type
đĄNullable Types
đĄValidation Exceptions
đĄNull Reference Exception
đĄLanguage Extensions
đĄException Handling
đĄInteroperability
Highlights
Introduction of discriminated unions, also known as type unions, a highly requested feature in C#.
Discussion of two new runtime types: the result type and the option type.
Explanation of the confusion surrounding the new types and their purpose.
Demonstration of how to work with these types in other languages and their potential implementation in C#.
The benefits of having a common type in the runtime for everyone to use.
The impact of these types on the consolidation of libraries and NuGet packages.
Showcasing a simple console application to emulate database operations and exception handling.
The common practice of using exceptions for flow control and its drawbacks.
How to use the new types to avoid the performance issues associated with exceptions.
The use of Language Extensions package to demonstrate the concept of option and result types.
The difference between option types and nullable types in terms of safety and enforcement.
How result types can represent success or failure more explicitly than exceptions.
The potential for a more elegant consumption experience with type unions in the future.
The current workaround of using warnings as errors to enforce the handling of nullable references.
The introduction of new language features to handle the option and result types more effectively.
The comparison between using exceptions and result types for error handling and performance.
The importance of training developers to understand and use the new types effectively.
The call to action for feedback on the new feature from the community and Microsoft's consideration of it.
Transcripts
hello everybody I'm Nick and in the
previous video I talked about a brand
new feature coming in cop at some point
the future called discriminated unions
and it's actually the most requested
feature of cop really ever and they're
more appropriately named type unions and
one of those points in that proposal
that we read is that there's two native
types coming in the runtime and that is
the result type and the option type and
many people are very confused as to what
those are what they do how are they
going to work and why are we getting
them in the first place so in this video
I'm going to show you what those types
are how they work in other languages and
how they're likely to work in cop now
this is something you can actually do
already through n packages and Microsoft
is addressing that in their Q&A which we
will by the way take a look at after I
show you the feature but I personally
think the fact that they're being added
is a net positive because if someone
wants to use them they would use the
runtime version part of the BCL so
everyone will have the exact same common
type and this will become very very
powerful for consolidation of libraries
and Y packages so let me show what I
have here I have a simple console
application and I have this user service
over here so all I really have here is
I'm trying to emulate something that is
maybe calling a repository or is calling
a DB context in anti frame or core but
the idea is I have some sort of database
in this case in memory and then I have a
get user method that returns anable user
trying to find it based on the ID and
then I have a create user method where
we have the email and the name very
simple model uh we pass the email we try
to validate it if it's invalid we throw
an exception hey you just used an
invalid email then I have a check on the
database on the email because that's my
unique identifier for this example hey
if it already exists then we throw an
exception and in the end if everything
is good we create a new user very simple
and those exceptions are validation
exceptions so if you want to try catch
validation exception and then get the
message you can and you get a message
out of it this is extremely common code
I see this all the time in many many
code bases now in the program.cs I'm
going to simulate how this is supposed
to work from a consumption standpoint so
first you would have your user service
and if we want to create a user would
say user service. create user Nick chops
and if I want ahead I tried to create
the same user twice the first one will
create it but as you might assume the
second one will throw an exception hey
this email already exists user with
email nickd tr.com already exists makes
sense now I could also just get the user
and because this is a nullable type I'm
using a user nullable over here I can
say if a user is null then you know user
does not exist through a message but it
also means that if I try to do something
like console. right line the name is and
let me just quickly fix that the name is
user.name well I have these yellow
squiggly lines telling me that there's a
possibility for a null reference
exception because we don't really know
if this user actually exists at this
point because this can return null this
is anable type so you might want to add
an if check and we can easily do that by
potentially checking the expression for
null so if the user is not null do that
and so on now something you might have
noticed about this feature is that it
isn't actually an error it is just a
warning even though we know for a fact
this can return null many languages
actually treat this as an error cop
because they introduced this feature in
cop 8 they couldn't just go ahead and
turn this into an error by default
because it would break a lot of code
bases if you want to adopt the feature
so they made a warning I think that's
bad because it sort of kills the purpose
of the feature being there in the first
place so what many people do is actually
they turn this warning into an error and
if there's a warning like this that turn
to an eror in the code base then you can
compile and they go ahead and they
address it and this will actually make
your codebase way more robust so that is
one of the problems but the other
problem is that we now have to throw
these exceptions that we later have to
catch so we have to say catch validation
exception so validation exception over
here then try to create the user and if
the user hasn't been created uh we catch
the exception we get the message and
then maybe we return a type which means
that if I have something like an i
result because this is an API and I'm
trying to return an HTTP response for
example well what I have to say here is
we'll take this then get HTTP response
then I'm going to try to create this
local function over here and I'm going
to say try to created pass it down over
here VAR created is this which returns
results do created normally but I want
to prevent the URL so I'm just going to
say created to return and okay and then
I'm going to say turn results. bad
request I'm going to pass down the
message very very quickly and then I
have my HP response which your map get
map post map put and so on are going to
use now this is all fine but first
exceptions are incredibly painfully slow
and using them like this to control the
flow of the application is in my opinion
a very very bad practice and this is
actually a very common criticism of
exceptions used in that way and of
course you have the nullability aspect
which isn't actually really enforceable
because even if you enforce them in your
own assembly whoever else is consuming
it doesn't have to actually use them and
that's where option and result come in
to fix both problems but before I show
you that I want to let you know we just
released two brand new costs on Dom
train call from Zero to Hero git and
GitHub actions those two costes are
authored by Scott sober who has
incredible experience in both topics and
they both take you from knowing nothing
about the topic into some really really
advanced stuff and what I loved about
those courses is that they both show you
what happens when things go wrong and
how to fix it now until the 18th of
August you can buy the GitHub actions
course and you will get the git course
for free Link in the description now
back to the video so what is that result
and option type well I'm going to go on
new and I'm going to install language
extensions. core and you get package
called language extensions. core why
because that language extension package
adds functional element and those two
types are technically monuts even though
I'm not going to actually talk about
bonage in this video but they add those
types in the code base in at least one
of their flavors now the way they're
going to work in the r time when type
unions are actually added is going to be
a bit different because the experience
of consuming them will be way way more
elegant but I'm going to try and show
you the idea behind them so let's say I
wanted to change this to use one of
those two types well what you would use
here is you would use an option type so
you would say not user but this returns
an option of type user what is an option
well an option is a discriminated Union
type which can have one of two states it
can be some value of a specific type or
it can be no value conceptually you can
think of it a bit like nullable type of
type T but the difference is and we see
that with both cases that in order to
lead to safer code you have to handle
both outcomes there's no way to try to
get out of handling both both scenarios
and that's the whole idea of
discriminated unions and type unions you
have to deal with both scenarios or as
many scenarios as there are the other
thing is the user this user can have
different outcomes it can have
successful States and fail States well
what you need to have here is not a user
but a result of type user and as you can
see by the way here nothing really
changed this is exactly the same from
the way I implemented this this returns
a nullable type over here but that is
automatically converted into an option
through an implicit conversion and
that's the same for the result over here
in the user I didn't have to say new
result of type user the user is
converted into a result automatically
however the exceptions now are turned
into what we call errors in a result
because a result can be either a success
or an error a failure basically and the
failure is represented in this
implementation using an exception and in
order to change my code base to accept
this I'm going to say uh return new
result of type user but we actually
return an exception which automatically
turns it into a failure and I'm going to
do the same here return new exception
and that's it so now I have my user
service changed and I know many people
already hate this because now they're
like okay why am I returning this but
trust me you will write safer code by
doing this now let's change the existing
code we had to use these new types and
I'm going to start with the nullable
aspect of it as you can see now I can no
longer say this is a user because it's
not a user it is actually an option of
type user okay but if I turn it into an
option I can no longer use the name how
am I supposed to get the properties of
that user well you can't what you can do
is you can try to switch on that object
and handle both of these situations you
are going to have to exhaustively handle
both scenarios now there's many methods
that you can use here but the one we
actually are going to get in cop is
you'll be able to switch on this and say
that if this is some value do this if
this is nonone value do this the way
language extension does it is we have to
say match and we have to match both
scenarios so if we have some value then
we have a user and if we have none value
then we have nothing and we need to
handle both situations now this looks
ugly because it doesn't really fit the
language in its current state but
eventually this will be a switch and
it's going to be pretty but what this
means is I can go ahead and say that hey
if a user exists then now I can access
the user object and I can say name over
here and the name is this or the the
user did not exist and that's it and now
if I was to run this as it is of course
we are creating the user here so that
should not be a problem I should just
see the name is whatever so my code will
work exactly the same however if I try
to get a user that did not exist so Nick
a then as you're going to see the user
did not exist I'm handling both
situations very very elegantly now of
course this would be way prettier if we
had the switch like I said because that
then would be you is this and you'll be
able to handle it like something like
this and if it was none you would have
something like this so you'd be way
closer to this experience than any other
experience and I think this looks pretty
pretty nice now option types also have
different approaches to this you can
actually say that user option do if some
then you can have just the happy path
handling so you can say hey if there is
some value then do this this is way way
more functional that what most people
are used to in cop but you can do that
and then you can also do the same with
if none we don't really know if those
things are going to be added in cop but
those are things that you can do
currently with language extensions if I
just revert to the previous state with
the match then I'd be able to show you
what's now happening with this approach
so now we no longer have have all that
going on if I want to get an ey result I
don't need a method to begin with I can
simply say that user service. create
user and actually I'm going to turn this
into just the result and remember this
type explicitly is result of type user
and that can only be success or failure
so I can say I result of HTTP response
equals result. match same thing I can
also map but I'm going to use match here
so if it is a success I'm going to say
return results. okay with that user if
it is an exception or a failure I'm
going to say results. bad request and
then exception do message here we go
very very easy very very simple this can
actually become even prettier here you
go and now I have all that code turned
into this and I do handle both
situations I have to say that if
something is handled correctly here's my
response if something is not handled
correctly then that's how I deal with
this and I don't have to throw
exceptions I can just propagate that if
I don't need to use it or I can simply
handle it when I need to handle it I
think this is a great addition to cop I
really really hope this is being added
and I do want to take a look at the Q&A
because Microsoft has addressed this in
the proposal so why do I need the option
type if I can do the same thing with n
and La reference types well the answer
is you might not need the option type at
all if you're comfortable with using NS
and for the same purpose however some
developers prefer the option types as it
has stronger enforcement it is all about
enforcing the usage and the consumption
through option it's not something you
can turn off you have to handle both
things that's where the power is coming
from and then again why do I need the
result type when I already have
exception handling many of the use cases
for the result type are solved by using
extension handling is C however you may
prefer to avoid extension handl which by
the way is very expensive in terms of
performance and require the caller to
deal with errors explicitly where errors
unexpected and occur commonly at runtime
it's a way better experience I've seen
this used all the way back in 2017
actually is when I first saw this result
and option types used in a production
code base when I first started work at a
massive company here in the UK and they
work they do actually lead to a better
code base they do have quite a bit of a
steep ask to start using them and
understand them and because they're not
part of the runtime there is a level of
training you need to do for your
developers to actually understand them
but once they do they work wonders and
then again in the end if we have them
already in third party libraries why are
they being added were they being added
because we want to standardize them and
have interoperability between libraries
I think it's a great feature I'm so so
happy Microsoft is adding it but I do
want to know from you what do you think
about this please leave a comment down
below and let me know and Microsoft is
watching these videos so any feedback
you have will also be taken into account
by Microsoft well that's all I had for
you for this video thank you very much
for watching and as always keep coding
5.0 / 5 (0 votes)