{"action":"created","issue":{"url":"https://api.github.com/repos/dotnet/roslyn/issues/5154","labels_url":"https://api.github.com/repos/dotnet/roslyn/issues/5154/labels{/name}","comments_url":"https://api.github.com/repos/dotnet/roslyn/issues/5154/comments","events_url":"https://api.github.com/repos/dotnet/roslyn/issues/5154/events","html_url":"https://github.com/dotnet/roslyn/issues/5154","id":105941149,"number":5154,"title":"Proposal: expression-based switch (\"match\") for pattern matching","user":{"login":"gafter","id":3804346,"avatar_url":"https://avatars.githubusercontent.com/u/3804346?v=3","gravatar_id":"","url":"https://api.github.com/users/gafter","html_url":"https://github.com/gafter","followers_url":"https://api.github.com/users/gafter/followers","following_url":"https://api.github.com/users/gafter/following{/other_user}","gists_url":"https://api.github.com/users/gafter/gists{/gist_id}","starred_url":"https://api.github.com/users/gafter/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/gafter/subscriptions","organizations_url":"https://api.github.com/users/gafter/orgs","repos_url":"https://api.github.com/users/gafter/repos","events_url":"https://api.github.com/users/gafter/events{/privacy}","received_events_url":"https://api.github.com/users/gafter/received_events","type":"User","site_admin":false},"labels":[{"url":"https://api.github.com/repos/dotnet/roslyn/labels/Area-Language%20Design","name":"Area-Language Design","color":"5319e7"},{"url":"https://api.github.com/repos/dotnet/roslyn/labels/Feature%20Request","name":"Feature Request","color":"fc2929"},{"url":"https://api.github.com/repos/dotnet/roslyn/labels/Feature%20Specification","name":"Feature Specification","color":"fc2929"},{"url":"https://api.github.com/repos/dotnet/roslyn/labels/Language-C%23","name":"Language-C#","color":"207de5"}],"state":"open","locked":false,"assignee":{"login":"gafter","id":3804346,"avatar_url":"https://avatars.githubusercontent.com/u/3804346?v=3","gravatar_id":"","url":"https://api.github.com/users/gafter","html_url":"https://github.com/gafter","followers_url":"https://api.github.com/users/gafter/followers","following_url":"https://api.github.com/users/gafter/following{/other_user}","gists_url":"https://api.github.com/users/gafter/gists{/gist_id}","starred_url":"https://api.github.com/users/gafter/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/gafter/subscriptions","organizations_url":"https://api.github.com/users/gafter/orgs","repos_url":"https://api.github.com/users/gafter/repos","events_url":"https://api.github.com/users/gafter/events{/privacy}","received_events_url":"https://api.github.com/users/gafter/received_events","type":"User","site_admin":false},"milestone":{"url":"https://api.github.com/repos/dotnet/roslyn/milestones/8","html_url":"https://github.com/dotnet/roslyn/milestones/C%23%207%20and%20VB%2015","labels_url":"https://api.github.com/repos/dotnet/roslyn/milestones/8/labels","id":962632,"number":8,"title":"C# 7 and VB 15","description":"\r\n\r\n<!---\r\n@huboard:{\"order\":0.375}\r\n-->\r\n","creator":{"login":"gafter","id":3804346,"avatar_url":"https://avatars.githubusercontent.com/u/3804346?v=3","gravatar_id":"","url":"https://api.github.com/users/gafter","html_url":"https://github.com/gafter","followers_url":"https://api.github.com/users/gafter/followers","following_url":"https://api.github.com/users/gafter/following{/other_user}","gists_url":"https://api.github.com/users/gafter/gists{/gist_id}","starred_url":"https://api.github.com/users/gafter/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/gafter/subscriptions","organizations_url":"https://api.github.com/users/gafter/orgs","repos_url":"https://api.github.com/users/gafter/repos","events_url":"https://api.github.com/users/gafter/events{/privacy}","received_events_url":"https://api.github.com/users/gafter/received_events","type":"User","site_admin":false},"open_issues":60,"closed_issues":11,"state":"open","created_at":"2015-02-02T23:41:34Z","updated_at":"2015-10-30T19:15:44Z","due_on":null,"closed_at":null},"comments":232,"created_at":"2015-09-11T03:59:43Z","updated_at":"2015-11-04T10:28:17Z","closed_at":null,"body":"This is a proposed extension to pattern matching as specified in #206. Contributions to fill in missing sections below would be welcome.\r\n\r\n### Purpose\r\n\r\nProvide a `switch`-like construct for use in expressions, that would have the following advantages over the `switch` statement:\r\n- An expression rather than a statement (so can be used embedded in an expression)\r\n- No break or fall-through semantics\r\n- The compiler would be required to check that some case branch always succeeds.\r\n\r\n### Syntax\r\n\r\nThe C# language syntax is augmented with the following syntactic productions:\r\n\r\n> *relational-expression*:\r\n> &nbsp;&nbsp;&nbsp;&nbsp;*match-expression*\r\n\r\nWe add the *match-expression* as a new kind of *relational-expression*.\r\n\r\n> *match-expression*:\r\n> &nbsp;&nbsp;&nbsp;&nbsp;*relational-expression* `match` *match-block*\r\n\r\nNote that `match` is a new contextual keyword.\r\n\r\n> *match-block*:\r\n> &nbsp;&nbsp;&nbsp;&nbsp;`(` *match-sections* `)`\r\n\r\nAt least one *match-section* is required.\r\n\r\n> *match-sections*:\r\n> &nbsp;&nbsp;&nbsp;&nbsp;*match-section*\r\n> &nbsp;&nbsp;&nbsp;&nbsp;*match-sections* *match-section*\r\n>\r\n> *match-section*:\r\n> &nbsp;&nbsp;&nbsp;&nbsp;`case` *pattern* *case-guard*<sub>opt</sub> `:` *expression*\r\n>\r\n> *case-guard*:\r\n> &nbsp;&nbsp;&nbsp;&nbsp;`when` *expression*\r\n\r\nIt is not proposed that *match-expression* be added to the set of syntax forms allowed as an *expression-statement*.\r\n\r\n### Semantics\r\n\r\nThe scope of pattern variables declared in the *pattern* of a *match-section* is the whole *match-section*.\r\n\r\nThe compiler gives an error unless it can prove (using a set of techniques that has not yet been specified) that the value of the expression on the left-hand-side of the *match-expression* always matches the pattern of some *match-section* that has no *case-guard*.\r\n\r\nThe type of the *match-expression* is the *least common type* of the expressions appearing to the right of the `:` tokens of the *match section*s.\r\n\r\nIt is an error if the compiler can prove (using a set of techniques that has not yet been specified) that some *match-section*'s pattern cannot affect the result because some previous pattern will always match.\r\n\r\nAt runtime, the result of the *match-expression* is the value of the *expression* of the first *match-section* for which the expression on the left-hand-side of the *match-expression* matches the *match-section*'s pattern, and for which the *case-guard* of the *match-section*, if present, evaluates to `true`.\r\n\r\n### Examples\r\n\r\nContributed by @orthoxerox:\r\n\r\n```cs\r\nvar areas =\r\n    from primitive in primitives\r\n    let area = primitive match (\r\n        case Line l: 0\r\n        case Rectangle r: r.Width * r.Height\r\n        case Circle c: Math.PI * c.Radius * c.Radius\r\n        case *: throw new ApplicationException()\r\n    )\r\n    select new { Primitive = primitive, Area = area };\r\n```\r\n"},"comment":{"url":"https://api.github.com/repos/dotnet/roslyn/issues/comments/153674119","html_url":"https://github.com/dotnet/roslyn/issues/5154#issuecomment-153674119","issue_url":"https://api.github.com/repos/dotnet/roslyn/issues/5154","id":153674119,"user":{"login":"jcdickinson","id":522465,"avatar_url":"https://avatars.githubusercontent.com/u/522465?v=3","gravatar_id":"","url":"https://api.github.com/users/jcdickinson","html_url":"https://github.com/jcdickinson","followers_url":"https://api.github.com/users/jcdickinson/followers","following_url":"https://api.github.com/users/jcdickinson/following{/other_user}","gists_url":"https://api.github.com/users/jcdickinson/gists{/gist_id}","starred_url":"https://api.github.com/users/jcdickinson/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jcdickinson/subscriptions","organizations_url":"https://api.github.com/users/jcdickinson/orgs","repos_url":"https://api.github.com/users/jcdickinson/repos","events_url":"https://api.github.com/users/jcdickinson/events{/privacy}","received_events_url":"https://api.github.com/users/jcdickinson/received_events","type":"User","site_admin":false},"created_at":"2015-11-04T10:28:16Z","updated_at":"2015-11-04T10:28:16Z","body":"> Would it not make sense to have * and var the same?\r\n\r\nI agree about not having multiple forms of syntax for the same thing. There are no backwards compatability concerns here, which means that having two forms of syntax has no justification whatsoever. I'd personally prefer to see `*` go away. As-per the original example:\r\n\r\n```\r\nvar areas =\r\n    from primitive in primitives\r\n    let area = primitive match (\r\n        case Line l: 0\r\n        case Rectangle r: r.Width * r.Height\r\n        case Circle c: Math.PI * c.Radius * c.Radius\r\n        case object o: throw new ApplicationException()\r\n    )\r\n    select new { Primitive = primitive, Area = area };\r\n```\r\n\r\n`Object` is the ultimate root object, so `*` is completely unnecessary for the same reasons that we don't use `catch (*)` in C#. Another though, take more syntax from `switch`:\r\n\r\n```\r\nvar areas =\r\n    from primitive in primitives\r\n    let area = primitive match (\r\n        case null: 0\r\n        case Line: 0\r\n        case Rectangle r: r.Width * r.Height\r\n        case Circle c: Math.PI * c.Radius * c.Radius\r\n        default: throw new ApplicationException()\r\n        // Variable name is optional, so this is also possible:\r\n        default o: int.Parse(o.ToString()) // Definitely going to work\r\n    )\r\n    select new { Primitive = primitive, Area = area };\r\n```\r\n\r\n> Dispatching result directly to compatible method. \r\n\r\nThat's conflating the lambda operator, which is confusing."}}