Hacker News
← Back

C# 9 Pattern Matching

4 years ago/64 comments/developers.redhat.com
5 years ago by infogulch

I'm looking forward to Discriminated Unions being finalized. One day... https://github.com/dotnet/csharplang/issues/113

5 years ago by gsuuon

F# is slowly making it's way into C#... but you could also just skip the wait and start using F# :p

5 years ago by thrower123

The thing about waiting for C# to pick over F# is that JetBrains keeps up with everything new the C# team does.

I really would like to make myself use F# more, but at the end of the day, the tooling is not as good as for C#, and it feels like a step backwards.

5 years ago by ducharmdev

I feel that. It always seems to come down to tooling; the moment you have to fight with tooling for a language, it immediately adds friction. Sure, individual developers can overcome these problems, but it still decreases the adoption rate of said language.

It makes me wonder what differed between the .NET and JVM runtimes, with .NET moving towards fewer languages, whereas the JVM supports more.

5 years ago by infogulch

You're like the fourth person to tell me that. Maybe I should listen...

5 years ago by hurril

I've been writing F# professionally for 1.5 years now and let me tell you: it is a BLISS! Came from Scala so no .NET experience at all before.

5 years ago by pjmlp

With the productivity drop of lack of tooling for some key .NET scenarios that only consider C# and VB.

5 years ago by bob1029

Pattern matching + switch expressions can make for really concise and functional state machines which can be validated for coverage at compile time.

5 years ago by mycall

I would love to see this in action. Do you know of any repos that are doing this?

5 years ago by ducharmdev

If you have the time, there's this great talk by Bill Wagner that goes over some of these newer features. You can also skip right to the pattern-matching section; he shows a good example of how powerful switch expressions can be.

https://m.youtube.com/watch?v=aUbXGs7YTGo

Alternatively, this page on the C# 8 release has good examples too. They show how you can leverage tuples to make them even more powerful.

https://docs.microsoft.com/en-us/dotnet/csharp/whats-new/csh...

5 years ago by spaetzleesser

I love these new additions because I like new stuff but I'll admit it's hard to keep up and use things with good taste. C# is becoming a BIG language similar to C++. But I guess that's the only way to get a broad user base long term.

5 years ago by mumblemumble

> C# is becoming a BIG language similar to C++.

Yes. And they're on roughly the same trajectory: start out as a relatively small object-oriented and procedural language, and then just keep piling on more and more and more features to make the procedural programming more ergonomic. Including by pulling in more and more stuff from functional programming.

On the one hand, it's hard for me to dislike adding pattern matching too much, because I do tend to prefer functional programming. On the other hand, I'm also familiar enough with OOP (it's been most my career) to know that there's a huge overlap between problems that pattern matching can solve, and problems that dynamic dispatch can solve.

The thing is, in these examples of using pattern matching in a language like C# or Python, I never see anyone even considering the object-oriented solution to the problem. They just show how gross the procedural version is. Which isn't quite enough in my book. You don't just want to show that some existing language features are a poor fit for the problem at hand, you want to show that all existing language features are a poor fit. And somehow, despite these being object-oriented languages, the object-oriented solution is never even being considered anymore.

Is it because OOP is that bad? Or is it because we've been badly taught? I know which answer is easier to argue for, but I'm less and less convinced that that's because it's the best answer.

5 years ago by jayd16

In a lot of ways I think the OOP approach is just too cumbersome.

If you imagine implementing a handler chain, the logic would be quite verbose and distributed. You might want to use an inline type definition. Then you might want to use an anonymous types, then lambdas.

Then you realize that pattern matching is just a sugared version of the OO handler chain.

5 years ago by mumblemumble

I was actually thinking something simpler; just having all your types implement an interface, and then following the general "tell, don't ask" dictum.

Handlers are useful for some more complex use cases, as is the visitor pattern, but they're frankly overused. It's often enough to create an interface and let the classes handle their own class-specific logic.

And polymorphism is not just a sugared version of pattern matching. Each gives you a different kind of flexibility. Polymorphism makes it easy to add new types to an existing set of operations, and pattern matching makes it easier to add new operations to an existing set of types.

Which one you need depends on your use case. The common knowledge can get a bit tricky here, though. For example, functional programming is often touted as being ideal for programming language experimentation, because you have pattern matching, but I have found that OOP is more to my taste in this area. The reason is because, nowadays, the set of basic operations a compiler or interpreter needs to do is fairly well-established and static. But the list of things you need to operate on - that is, the set of features in the language you're implementing - will change as you add or remove features from the language.

5 years ago by CornCobs

In my personal opinion when I'm reading code and trying to follow execution flow, OOP's "Everything happens elsewhere" approach is really annoying. In a Java codebase for example I would need to find all implementing classes, then search for that one method being called in each separate file. This means opening multiple files and searching for a few lines of code in each file, just to see what happens.

Written in a pattern-matching style there is a nicer correspondence between code-locality and execution-locality - which matches my mental model much more nicely, rather than OOP's colocation of different behaviors on the same entity

5 years ago by kemiller2002

This is my fear. C# keeps adding things to appeal to a different user base. What I've seen (anecdotally) is that most C# devs don't know or don't use the new features. This pretty much means they are useless to me, because even though I can use them and understand the new features, other people can't. The new code isn't maintainable to most people beyond me. Yes, I can go and show them and train people, but really it comes down to coding the imperative/oo way is what the majority of people are used to.

5 years ago by emodendroket

The popularity of ReSharper really helps with this, I find. People pick up the new features because ReSharper constantly recommends them.

5 years ago by cfn

Resharper has also helped my code to "evolve" alongside the language. In fact I learned LINQ with it. It is also very easy to compare the different solutions for readability in each case.

5 years ago by dnautics

Go is a relatively simple language that doesn't look like it's getting much bigger and I'm pretty sure it has a fairly broad user base.

5 years ago by emodendroket

Dwarfed by that of C#, but it’s also going for something rather different that was never attainable by C# in the first place.

Also, I’m kind of on the fence about Go. I was charmed by how easy it is to read and their error handling strategy admittedly has benefits. But it is awfully tedious to write.

5 years ago by politician

I wrote C# for a long time, incl. low-level systems work at the C#/C++ boundary, heavy reflection and simulation systems, and numerical processing.

I prefer Go immeasurably. All of the same scope is achievable, but I'm not constantly assaulted by new syntax, unwieldy OO hierarchy towers of Babel, or broken data frameworks.

foo, err := DoIt() if err != nil { return err }

is a small price to pay for sane control flow in the presence of exceptions. I can debug code in Vim without needing Reflector and Visual Studio to make sense of what I'm looking at.

5 years ago by dnautics

No argument.. I strongly dislike go, myself.

5 years ago by Igelau

Go has the opposite problem. It's not getting big enough. Last I checked, they couldn't be bothered to add integer exponentiation.

5 years ago by recursive

C# also doesn't have integer exponentiation.

5 years ago by dustinmoris

Ironically I'm mostly abandoning C# and using Go for the majority of my new development now. I really like the simplicity and stability of Go. The compiler speed, the tooling, gofmt, and lots of other goodies just make it a very refreshing change. I'm sure in 5 years time Go will also feel less refreshing, but I have a feeling that my Go code today will not look vastly different to my Go code in 5 years time and that is very attractive. Also Go really allows one to hire anyone. You can literally just hire a smart person and let them learn Go on their first day on the job which will make them good enough to start picking up the first tasks and be productive. There are not many languages which can do that.

5 years ago by merb

> You can literally just hire a smart person and let them learn Go on their first day on the job which will make them good enough to start picking up the first tasks and be productive.

you can be productive on the first tasks in any language. that is a stupid pitch. bad code can be written in any language, especially in golang. I've seen as many bad code in golang than in other languages. and fixing bad code in golang is way worse than in some other languages.

5 years ago by emodendroket

That's the pitch but I'm also kind of tired of reading Java with Go syntax.

5 years ago by ed_elliott_asc

Problem is if they don’t keep making changes people start asking why it has been abandoned

5 years ago by belinder

> An interesting case is the is not null pattern. This will check whether the reference is not null. Using != null may check something different when the type overloads the != operator.

If it doesn't use the != operator then what does it use? How does it work with Nullable<T> which relies on that

5 years ago by MarkSweep

I think this sharplab link might help[1]. You can see that pattern matching generates the same code as using "== null". You can see that Nullable<T> is handled when the parameter type is a nullable int. When a Nullable<T> that has no value (HasValue == false) is cast to Object, it gets converted to a null reference. So the comparison will work as expected.

When operating overloading is involved[2], different code is generated.

[1]: https://sharplab.io/#v2:C4LglgNgPgAgTARgLACgYGYAEMEDZtyYDCmA...

[2]: https://sharplab.io/#v2:C4LglgNgPgAgTARgLACgYGYAE9MGFMDeqmJ2...

5 years ago by rzzzt

Probably always the default implementation of != (reference non-equality for objects), irrespective of whether an overloaded version exists.

This SO answer has a snippet of the specification that may be relevant: https://stackoverflow.com/a/7346086

5 years ago by rohittidke

i have been using C# since 2010.I find it a good language but I believe the future is not for strict statically typed languages and but for smart linters which probably could take over compilers.

The effort you put into strict types doesn't deliver the returns. Languages like Typescript incmy opinion are the best as they provide optional typing and support things mixins for example which is difficult to implement in C#

5 years ago by The_rationalist

if (person is not null)

I really like it, it is more instantaneously readable than the usual != as it is more literate.

5 years ago by jayd16

As mentioned in the link. Those are not equivalent because the != operator can be overloaded. I believe this is a less verbose version of

    if(Object.ReferenceEquals(person, null))
5 years ago by mrkeen

Person should have type Person, and null should have type Null. Then the compiler could make sure you didn't ever mix the two up! But I guess that ship sailed a while ago, and enough has been written on the matter.

I think I dislike `is not` though, mostly because `!=` still exists so now there's two of them. I already use the wrong null check in SQL[1], I don't want to use it in C# too.

[1] https://stackoverflow.com/questions/5658457/not-equal-operat...

> To compare if your value is not null, you use IS NOT NULL, while to compare with not null value, you use <> 'YOUR_VALUE'. I can't say if my value equals or not equals to NULL, but I can say if my value is NULL or NOT NULL. I can compare if my value is something other than NULL.

5 years ago by nikeee

> think I dislike `is not` though, mostly because `!=` still exists so now there's two of them.

Note that "!= null" may behave differently than "is not null". != is an operator that can be overloaded, "is not" is not. Same counts for "is" and == when checking for null.

5 years ago by Guillaume86

> Person should have type Person, and null should have type Null. Then the compiler could make sure you didn't ever mix the two up! But I guess that ship sailed a while ago, and enough has been written on the matter.

You can somewhat get that in C# nowadays: https://docs.microsoft.com/en-us/dotnet/csharp/nullable-refe...

5 years ago by moomin

It's nice, but C# already had `person is {}` which whilst it requires a bit more familiarity with C# extends to more uses like `person is { name: "Rationalist" }`.

5 years ago by MarkSweep

You can also do "person is object", which seems to make sense to me.

5 years ago by alkonaut

It's also in some edge cases more correct, because you can't trust != to actually check for null. That edge case is when your (favorite) coworker did

public static bool operator != (YourType x, YourType y) => DateTime.Now.DayOfWeek == DayOfWeek.Thursday;

Note to self when designing a language: no operator overloads on reference types.

5 years ago by doodpants

Ok, but if you have a coworker who's going to maliciously overload operators to behave differently than expected, then all bets are off and you have much bigger problems than how to check for null.

5 years ago by jayd16

Its not malicious or unheard of. Unity, a very popular game engine, overloads the == operator as well as the implicit boolean cast for their built in types. They do this because their types adhere to a specific lifecycle. When an object is dead, == null is true.

I'm not a fan and its not super common but it happens.

5 years ago by alkonaut

I was half joking, obviously this is hopefully not done out of malice and hopefully whoever overloads the operator still handles the case != null logically equal to the expected way. There could be smaller differences than true correctness like performance too, not least since the != will be a virtual call that must be resolved, and also the overloaded implementation may or may not be as efficient as ā€œis not nullā€ is.

This is a similar same issue as the ā€œwhat’s wrong with using String instead of stringā€ when it only breaks if someone adds their own type and calls it String, or aliases a type to String (with a capital S). This actually happens in actual code bases for various reasons not necessarily malicious.

5 years ago by Igelau

C# has some wonderful quality of life improvements over, say, Java. I had to learn it in a rush for a job and really loved the language.

Unfortunately, it was the worst job ever. Abusive, corrupt environment. I found a subtle accounting glitch that no one else seemed to quite understand. Assuming good faith, I showed mathematical proof for it, and I was canned shortly thereafter. On its own, the glitch wasn't too serious, but I suspect people were nervous that I was digging too close to something else.

Never bothered to set up the env at home again after that on account of the foul taste in my mouth, but that was hardly C#'s fault. Just found other things to do.

5 years ago by haolez

Heard a similar story from a close friend. Also a C# shop. A few months after, the glitch was indeed due to corruption and some middle managers were stealing money. They went to jail soon afterwards.

Maybe this just means that C# is widely used in places where fraud can result in big gains.

EDIT: what I meant is that C# is probably used a lot in accounting departments, for example. I'm not trying to imply that C# invites fraud :)

5 years ago by kahrl

Maybe this just means that C# is widely used in places where fraud can result in big gains.

No.

5 years ago by damagednoob

Are you sure? I mean, there's at least _2_ data points.

5 years ago by undefined
[deleted]
5 years ago by dgritsko

It's more just that "C# is widely used".

Daily Digest

Get a daily email with the the top stories from Hacker News. No spam, unsubscribe at any time.