[HN Gopher] C# 9 Pattern Matching
___________________________________________________________________
C# 9 Pattern Matching
Author : benaadams
Score : 53 points
Date : 2021-04-06 11:43 UTC (1 days ago)
(HTM) web link (developers.redhat.com)
(TXT) w3m dump (developers.redhat.com)
| bob1029 wrote:
| Pattern matching + switch expressions can make for really concise
| and functional state machines which can be validated for coverage
| at compile time.
| spaetzleesser wrote:
| 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.
| kemiller2002 wrote:
| 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.
| emodendroket wrote:
| The popularity of ReSharper really helps with this, I find.
| People pick up the new features because ReSharper constantly
| recommends them.
| cfn wrote:
| 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.
| emodendroket wrote:
| The Linq suggestions are the only one where I frequently
| have to reject them for being unreadable, but overall yes
| I agree.
| mumblemumble wrote:
| > 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.
| jayd16 wrote:
| 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.
| mumblemumble wrote:
| 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.
| dnautics wrote:
| 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.
| emodendroket wrote:
| 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.
| politician wrote:
| 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.
| emodendroket wrote:
| The thing is, yeah, any one of those verbose things
| wouldn't be a big deal. But there are actually quite a
| few and it adds up over time.
| dnautics wrote:
| No argument.. I strongly dislike go, myself.
| dustinmoris wrote:
| 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.
| emodendroket wrote:
| That's the pitch but I'm also kind of tired of reading Java
| with Go syntax.
| merb wrote:
| > 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.
| Igelau wrote:
| Go has the opposite problem. It's not getting big enough.
| Last I checked, they couldn't be bothered to add integer
| exponentiation.
| recursive wrote:
| C# also doesn't have integer exponentiation.
| Garvey wrote:
| It has since .Net 4.0, but does require using BigInteger
|
| https://docs.microsoft.com/en-
| us/dotnet/api/system.numerics....
| recursive wrote:
| That's a stretch. There's no language support for it in
| terms of an operator, and it's in a package that's not
| referenced by default.
| ed_elliott_asc wrote:
| Problem is if they don't keep making changes people start
| asking why it has been abandoned
| infogulch wrote:
| I'm looking forward to Discriminated Unions being finalized. One
| day... https://github.com/dotnet/csharplang/issues/113
| gsuuon wrote:
| F# is slowly making it's way into C#... but you could also just
| skip the wait and start using F# :p
| infogulch wrote:
| You're like the fourth person to tell me that. Maybe I should
| listen...
| hurril wrote:
| 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.
| thrower123 wrote:
| 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.
| rohittidke wrote:
| 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#
| [deleted]
| Igelau wrote:
| 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.
| haolez wrote:
| 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 :)
| kahrl wrote:
| _Maybe this just means that C# is widely used in places where
| fraud can result in big gains._
|
| No.
| [deleted]
| damagednoob wrote:
| Are you sure? I mean, there's at least _2_ data points.
| Someone wrote:
| Not even that. Could be two comments about the same data
| point.
| merb wrote:
| well with this growth rate it could mean that in a few
| months with have dozens of c# companies with abusive
| managers.
| dgritsko wrote:
| It's more just that "C# is widely used".
| The_rationalist wrote:
| if (person is not null)
|
| I really like it, it is more instantaneously readable than the
| usual != as it is more literate.
| alkonaut wrote:
| 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.
| doodpants wrote:
| 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.
| jayd16 wrote:
| 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.
| alkonaut wrote:
| 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.
| mrkeen wrote:
| 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.
| Guillaume86 wrote:
| > 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...
| nikeee wrote:
| > 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.
| moomin wrote:
| 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" }`.
| MarkSweep wrote:
| You can also do "person is object", which seems to make sense
| to me.
| jayd16 wrote:
| 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))
| belinder wrote:
| > 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
| rzzzt wrote:
| 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
| MarkSweep wrote:
| 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...
___________________________________________________________________
(page generated 2021-04-07 23:02 UTC)