[HN Gopher] C# Pattern Matching
       ___________________________________________________________________
        
       C# Pattern Matching
        
       Author : brudgers
       Score  : 88 points
       Date   : 2020-02-03 14:17 UTC (1 days ago)
        
 (HTM) web link (docs.microsoft.com)
 (TXT) w3m dump (docs.microsoft.com)
        
       | macca321 wrote:
       | Apologies, but here's the obligatory link to my OneOf exhaustive
       | type matching library: https://github.com/mcintyre321/OneOf
        
       | totalperspectiv wrote:
       | At this point I would not be sad if I was forced to use C# for
       | some reason.
        
         | bob1029 wrote:
         | You should try it out sometime, regardless of coercion. There
         | isn't much of a barrier to entry anymore. Even installing
         | VS2019 is a pleasant experience now.
         | 
         | I have yet to meet a developer who gave C# a legitimate try and
         | then decided it was entirely not for them. That said, I only
         | personally know developers who are working in the realm of B2B
         | application development, so perhaps there are other
         | incompatible use cases that I am blind to from my current
         | perspective.
        
       | mindfulplay wrote:
       | Such a beautiful, elegant language. Simple to grasp and lets the
       | compiler handle all that legitimate complexity.
       | 
       | Wish more language designers would respect code authors like
       | these designers do.
        
         | mumblemumble wrote:
         | I suspect that it's not an issue of respect so much as an issue
         | of governance. C# remains a commercial language, wholly owned
         | by a single corporate entity. That, I think, allows its
         | maintainers some luxuries that community languages don't enjoy.
         | Chief among them is a whole team of full-time language
         | designers and implementers who can sustain a sort of deep
         | concentration 40-ish hours a week for years on end. I'm pretty
         | sure it's closing in on a decade that there's been talk about
         | how to implement pattern matching into C#, and I'm absolutely
         | sure that a lot of blood, sweat, and tears went into it. But
         | that kind of effort is more manageable, on a personal level, if
         | you're getting paid to do it and if most the thornier bits of
         | the process are happening in a private-ish space and among a
         | small group of people you know well.
         | 
         | By contrast, with a community language where these decisions
         | are made in public, by committee, and perhaps by a team of
         | volunteers, it seems like things are always just a bit more
         | strained. I'm sure some of the more famous PEPs took a huge
         | personal toll on GvR, and there's no doubt that they caused a
         | lot of high emotions. I see similarly troublesome patterns in
         | Nim and Scala, where it would seem that "trying to avoid too
         | much conflict with people who are forcefully communicating
         | strongly held opinions over a medium like the Internet where
         | it's difficult to modulate emotions" can be a real factor in
         | the decision of what language features to include and how. And,
         | in that kind of environment, it's probably particularly
         | difficult to keep the Internet, with all its . . .
         | Internetiness, at bay for long enough to really make sure
         | you've got all the details dialed in right. Much easier, I
         | imagine, to go for the punt and get the whole business over
         | with.
        
           | Kipters wrote:
           | _Technically_ it 's owned by .NET Foundation now, but
           | admittedly it's composed of MSFT people by a large part.
           | Also, language design happens on GitHub, and the community is
           | encouraged to get involved.
        
         | 0xdead wrote:
         | Why are you being downvoted?
        
           | dang wrote:
           | Please don't do this here.
           | 
           | https://news.ycombinator.com/newsguidelines.html
        
           | moogleii wrote:
           | Perhaps because he's somewhat implying that other languages
           | aren't doing this, but C# is actually kind of late to the
           | game here.
        
             | mumblemumble wrote:
             | It's not _that_ late to the game, considering its paradigm.
             | How many other large object-oriented imperative languages
             | have it? Not C++ or Objective-C or Java. Kotlin has
             | destructuring, but not full pattern matching.
        
       | The_rationalist wrote:
       | From PHP 8 union types to C# pattern matching, I find it
       | beautiful how languages tends to have more and more similar
       | feature sets.It's like we're reaching a consensus on which
       | language constructs are beneficial.
        
       | S_A_P wrote:
       | Resharper has proven to be a great way for me to start learning
       | and integrating new language features. I code in my original
       | style and resharper suggests changes based on new features like
       | pattern matching. At first I didnt see the benefit, but this is a
       | hugely powerful feature once you start to wrap your mind around
       | it.
        
         | qwerty456127 wrote:
         | Indeed. A cool feature I love too. I miss this a lot when
         | coding Python (in PyCharm) and JavaScript (in VS.Code).
        
         | keithnz wrote:
         | as an aside, if you got Rider as part of your resharper
         | subscription, try it out, it is basically a drop in replacement
         | for visual studio but faster and with many many little quality
         | of life improvements you never knew you needed :)
        
           | tablloyd wrote:
           | I've recently switched to Rider full time from VS, so far
           | it's been a really good experience & has fixed the main
           | issues that I was experiencing with VS.
           | 
           | I've found it quite problematic to reliably connect to
           | private NuGet feeds though which is a bit of a pain.
        
           | to11mtm wrote:
           | I started using Rider recently.
           | 
           | It's faster yes, but seems to be a bit more memory hungry out
           | of the gate than VS+Resharper.
           | 
           | There is one HUGE thing I miss however - the Package Manager
           | console. There's still a few things I have to do in there and
           | thus have to switch back to VS.
        
           | bradenb wrote:
           | Does Rider work as a XAML designer yet?
        
           | qwerty456127 wrote:
           | > replacement for visual studio but faster
           | 
           | How can a IntelliJ Idea derivative written in Java be faster
           | than VistalStudio which is native code? Both Idea and PyCharm
           | work much slower than VisualStudio on my machine.
        
             | eberkund wrote:
             | Because VS has limitations on the amount of memory it can
             | use and although they have been working on this, there is
             | still functionality which is highly single threaded whereas
             | Rider tends to offload most of the functionality from the
             | UI thread into background processes.
        
           | bob1029 wrote:
           | The spell checker is probably the single greatest feature in
           | Rider. It works really well on composite type names. E.g.
           | 'CustomerPreferences' would not get a squiggle under it for
           | spelling, but 'CusomerPreferences' would. Performance is
           | arguably better in most circumstances, but it doesn't support
           | some of the bleeding edge .NET Core functionality as well as
           | VS2019 does.
        
             | keithnz wrote:
             | It also doesn't support some dried up crusty .NET
             | functionality like webforms either (it compiles it fine,
             | but doesn't have the code generation tools that VS has )
        
             | SigmundA wrote:
             | Resharper spell checks in VS for me too.
        
       | qwerty456127 wrote:
       | Cool. I bloody wish Python is going to introduce this (and
       | immutable (single-assign) variables) in near future.
        
       | zwieback wrote:
       | Is type-sensitive code totally acceptable now? I do use it at
       | times but generally try to avoid it.
        
         | AndrewDucker wrote:
         | C# as standard uses camelCase for internal variables and
         | UpperCamelCase for public variables, properties and methods.
         | 
         | https://docs.microsoft.com/en-us/dotnet/standard/design-guid...
        
           | moron4hire wrote:
           | That's not what he meant. It's not the casing of the names,
           | it's the switching on specific types, rather than building
           | interfaces and using generic programming.
        
             | AndrewDucker wrote:
             | Ah, thank you. That's what I get for commenting when tired!
        
         | moron4hire wrote:
         | I'd say this is probably a bad example of usage for the
         | feature. I use pattern matching in a few places in my own code-
         | base, and it's almost always on interfaces that have a large
         | set of extension methods applied. It's kind of like an entity-
         | component architecture, except the components are added at
         | compile-time, rather than run-time.
         | 
         | Unfortunately, real-life use scenarios are verbose and involved
         | and require a lot of background context that detracts from just
         | demonstrating the syntax. This is just demonstrating the
         | syntax. Standard patterns of software design still apply.
        
         | twblalock wrote:
         | I'd rather use this than the visitor pattern.
        
         | akdor1154 wrote:
         | I think it's used as an equivalent to discriminated unions,
         | which are generally loved in languages which have them.
        
         | seanmcdirmid wrote:
         | As long as you use virtual dispatch, an indirected jump table,
         | or some form of run-time tagging, you are writing type-
         | sensitive code whether you have dedicated syntax and types for
         | it or not.
        
         | jdmichal wrote:
         | It should be avoided, but there are legitimate use-cases.
         | Deserialization, for example, might yield a few different
         | types. Especially if you don't control the endpoint and the
         | data back is a mess.
         | 
         | When it is used, it's _very_ nice to have help from the
         | language. I much prefer that to some kind of purist,  "they
         | shouldn't do that so we won't help". I certainly miss having
         | type guards when I work in Java.
        
       | kag0 wrote:
       | I wrote up how I'd do this in scala, just to compare and contrast
       | val shape: Option[Shape] = ???         shape.map {           case
       | Square(0) | Circle(0)               => 0           case
       | Triangle(b, h)  if b == 0 || h == 0 => 0           case
       | Rectangle(l, h) if l == 0 || h == 0 => 0                case
       | Square(side)              => side * side           case
       | Circle(radius)            => radius * radius * math.Pi
       | case Triangle(base, height)    => base * height / 2
       | case Rectangle(length, height) => length * height         }
       | 
       | what I noticed                 * scala doesn't have a way for
       | cases to fall through, so the first cases have to each declare
       | that the result is 0. it would be cool if we could use something
       | in place of '=>' to make the case fall through.         * C#
       | doesn't have structural matching, so the 'when' keyword is used
       | more often.         * scala's pattern matching is exhaustive so
       | if we assume the shapes are in a sealed type hierarchy then we
       | don't need a default case.          * it's idiomatic to use
       | 'Option' instead of null in scala, but there are lots of
       | libraries in c# that offer option monads, so it's more a point of
       | what's idiomatic than what's possible.
        
         | jolux wrote:
         | C# 8 also has nullable reference types, i.e. comprehensive
         | nullability analysis, which is comparable though not identical
         | to an option type. I really wish for exhaustive pattern
         | matching and ADTs in C#, though.
        
       | jesseryoung wrote:
       | I've always seen switch statements as an anti-pattern in C#.
       | These examples however, do demonstrate neat time saving
       | techniques.
       | 
       | Does anybody have examples of real-world use cases that take
       | advantage of this that couldn't (or shouldn't) be solved in a
       | more OO way (Visitor, Strategy, Template Method, etc)
        
         | sixothree wrote:
         | I try to use switches only for enums or things with a 1 to 1
         | simple mapping. Enums to strings for example. Although even
         | there my preference is to use an attribute on the enum.
        
       | rkagerer wrote:
       | Here's an example of the new syntactic sugar:
       | public static double ComputeArea(object shape) {
       | switch (shape) {                 case Square s:
       | return s.Side * s.Side;                 case Circle c:
       | return c.Radius * c.Radius * Math.PI;                 case
       | Rectangle r:                     return r.Height * r.Length;
       | default:                     throw new ArgumentException(
       | message: "shape is not recognized",
       | paramName: nameof(shape));             }         }
       | 
       | The _when_ clause can be used to deal with special cases (e.g. to
       | avoid division by 0 when a dimension is 0).
        
         | ape4 wrote:
         | Its cool but I would call it switch-by-class-type instead of
         | pattern matching.
        
         | aar0nsa3nz wrote:
         | With C# 8 you can also write it as:                 public
         | static double ComputeArea(object shape) =>         shape switch
         | {           Square s => s.Side * s.Side,           Circle c =>
         | c.Radius * c.Radius * Math.PI,           Rectangle r =>
         | r.Height * r.Length           _ => throw new ArgumentException(
         | message: "shape is not recognized",                  paramName:
         | nameof(shape))         };
        
           | acidictadpole wrote:
           | Is `match` a reserved word in C#? I don't use it that much,
           | but have used scala and F# pattern matching and they all use
           | the term `match`, which seems more intuitive.
        
             | moogly wrote:
             | It's not reserved (and that's probably why it's not used).
             | Most teams working on languages with a decently long
             | history are very reluctant to add new keywords, because it
             | will break preexisting code. `match` is a very common
             | variable name, not only in relation to regexes. There are
             | of course ways to do contextual parsing so that you can
             | introduce new keywords (I believe this was done in C# with
             | the LINQ extensions), but it complicates things for all
             | eternity, so you want to avoid it.
        
               | zenexer wrote:
               | C# isn't too hesitant to introduce new keywords because
               | it supports contextual keywords.[0] Many C# keywords are
               | also valid identifiers. In this case, using `match` in
               | place of `where` probably wouldn't have introduced any
               | incompatibilities.
               | 
               | In fact, `where` isn't a reserved keyword, either--you
               | can have an identifier named `where`.[1]
               | 
               | To an existing C# programmer, `where` makes a lot of
               | sense, since it's used for matching elsewhere (e.g.,
               | LINQ).
               | 
               | [0]: https://docs.microsoft.com/en-
               | us/dotnet/csharp/language-refe...
               | 
               | [1]: https://docs.microsoft.com/en-
               | us/dotnet/csharp/language-refe...
        
           | derision wrote:
           | public static double ComputeArea(object shape) =>
           | shape switch {            Square s => s.Side * s.Side,
           | Circle c => c.Radius * c.Radius * Math.PI,
           | Rectangle r => r.Height * r.Length,           _ => throw new
           | ArgumentException( message: "shape is not recognized",
           | paramName: nameof(shape));        }
        
             | aar0nsa3nz wrote:
             | Sorry, I couldn't figure out how to write a code block.
        
               | derision wrote:
               | Two spaces in front of each line
        
           | moron4hire wrote:
           | There are also linters [0] available for checking that your
           | cases are exhaustive, which can even be configured to emit
           | the lack of exhaustive checking as an error, rather than just
           | a message or warning.
           | 
           | [0] Roslyn Analyzers: https://docs.microsoft.com/en-
           | us/visualstudio/code-quality/r...
        
           | Someone1234 wrote:
           | Their long game is to slowly convert C# into F# without
           | anyone realizing it. They're roughly half way through
           | already.
        
       | throwawa66 wrote:
       | Pattern matching is so much better in F#. C# gets more and
       | bloated to the point of paralysis. It's not yet there but I;m
       | sure it will at some point.
        
         | czechdeveloper wrote:
         | Every single feature C# got in past years increased my
         | productivity.
         | 
         | I understand that it may cause issues to new learners, but
         | overall, what of them do you consider bloat?
        
           | throwawa66 wrote:
           | Wait till you get to work in some complex code bases and
           | you'll understand why jamming all kinds of idioms into one
           | language can become a disaster. It's a tool after all, if you
           | know how to use it properly you don't paint yourself into a
           | corner. However, too much flexibility can lead to many
           | problems in larger teams. Good luck!
        
             | wvenable wrote:
             | Java proves that limiting language features for
             | "simplicity" just pushes the complexity somewhere else and
             | generally much worse.
             | 
             | C++ is usually taken as a language with too many features
             | but really it just has a few very flexible features and
             | people abused those features to do all kinds of
             | metaprogramming. As C++ has been adding more native
             | metaprogramming idioms it has actually been getting simpler
             | to code in.
        
               | gambler wrote:
               | The only thing Java proved about language design is that
               | popularity and good language design have zero
               | correlation.
               | 
               | If you want to see simplicity that stood the test of
               | time, look at Smalltalk or Lisp.
        
             | moron4hire wrote:
             | I don't know, what's easier to understand? Sorting a list
             | with an IComparer instance that you have to implement in a
             | concrete data type somewhere, or just tossing it a lambda
             | expression? Just because it's new syntax doesn't mean it's
             | automatically more difficult to understand the language.
        
               | throwawa66 wrote:
               | I got nothing against functional programming, I embrace
               | it. However, im stating again, shoving everything under
               | one umbrella is bound to create a complex monster.
               | Functional programming is actually easier to understand
               | in F# rather than C#, the idioms do translate but
               | clunkily. Do yourseves a favor and spend some time
               | outside C# and you'll come back illuminated.
               | 
               | Not saying C# is bad, thats what you all seem to
               | understand though.
               | 
               | Good luck to you all
        
               | graphememes wrote:
               | You find F# easier to work with. That's all. Doesn't mean
               | others _must_ share your opinion. Good luck to you.
        
               | throwawa66 wrote:
               | Yes, its all subjective, I know. But stepping out of the
               | garden is what I'd like people to take out of this.
               | Saying C# is the most beautiful language (like some
               | commenter states) is true only if you haven't dabbled in
               | many languages. And once you do you feel stupid for
               | having had this conviction in the first place. Ive used
               | C# throughout my career, I don't diss the language or the
               | ecosystem, but other things are to be considered as well
               | and cargoculting is a thing
        
           | tabtab wrote:
           | There may be a point where the total economic cost of newbie
           | training exceeds the benefits of improving efficiency for the
           | experienced. C++ arguably did that. Another problem is that
           | people will use different languages if the learning curve
           | grows too high.
        
         | konamicode wrote:
         | Unlike in C# pattern matching in F# is exhaustive. I'm guessing
         | this is what was meant by "better".
        
           | throwawa66 wrote:
           | Yes, i find that a good argument especially if you plan on
           | using this feature a lot it can save you from shooting
           | yourself in the foot. It also is a better idiom in F#, nicer
           | to grok, but that's subjective.
           | 
           | However, only direct experience will make you reconsider.
           | 
           | I've seen a discriminated union implementation in C# the
           | other day and was repulsed.
        
       ___________________________________________________________________
       (page generated 2020-02-04 23:00 UTC)