[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)