{"action":"created","issue":{"url":"https://api.github.com/repos/dotnet/roslyn/issues/206","labels_url":"https://api.github.com/repos/dotnet/roslyn/issues/206/labels{/name}","comments_url":"https://api.github.com/repos/dotnet/roslyn/issues/206/comments","events_url":"https://api.github.com/repos/dotnet/roslyn/issues/206/events","html_url":"https://github.com/dotnet/roslyn/issues/206","id":56325970,"number":206,"title":"Proposal: Pattern matching and record types","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/1%20-%20Planning","name":"1 - Planning","color":"cccccc"},{"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/Language-C%23","name":"Language-C#","color":"207de5"},{"url":"https://api.github.com/repos/dotnet/roslyn/labels/Language-VB","name":"Language-VB","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":null,"comments":13,"created_at":"2015-02-03T02:39:58Z","updated_at":"2015-02-05T15:59:46Z","closed_at":null,"body":"Pattern Matching for C#\r\n=======================\r\n\r\nPattern matching extensions for C# enable many of the benefits of algebraic data types and pattern matching from functional languages, but in a way that smoothly integrates with the feel of the underlying language. The basic features are: record types, which are types whose semantic meaning is described by the shape of the data; and pattern matching, which is a new expression form that enables extremely concise multilevel decomposition of these data types. Elements of this approach are inspired by related features in the programming languages [F#](http://www.msr-waypoint.net/pubs/79947/p29-syme.pdf \"Extensible Pattern Matching Via a Lightweight Language\") and [Scala](http://lampwww.epfl.ch/~emir/written/MatchingObjectsWithPatterns-TR.pdf \"Matching Objects With Patterns\").\r\n\r\n## 1 <a name=\"1\" />Record Type Declaration\r\n\r\nThe syntax for a `class` or `struct` declaration is extended to support value parameters; the parameters become properties of the type:\r\n\r\n>*class-declaration*:\r\n&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;*attributes*<sub>opt</sub> *class-modifiers*<sub>opt</sub> *partial*<sub>opt</sub> `class` *identifier* *type-parameter-list*<sub>opt</sub> *record-parameters*<sub>opt</sub></span> *class-base*<sub>opt</sub> *type-parameter-constraints-clauses*<sub>opt</sub> *class-body*\r\n\r\n>struct-declaration:\r\n&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;*attributes*<sub>opt</sub> *struct-modifiers*<sub>opt</sub> *partial*<sub>opt</sub> `struct` *identifier* *type-parameter-list*<sub>opt</sub> *record-parameters*<sub>opt</sub> *struct-interfaces*<sub>opt</sub> *type-parameter-constraints-clauses*<sub>opt</sub> *struct-body* `;`<sub>opt</sub>\r\n\r\n>*record-parameters*:\r\n&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;`(` *record-parameter-list*<sub>opt</sub> `)`\r\n\r\n>*record-parameter-list*:\r\n&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;*record-parameter*\r\n&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;*record-parameter-list* `,` *record-parameter*\r\n\r\n>*record-parameter*:\r\n&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;*attributes*<sub>opt</sub> *type* *identifier* *record-property-name*<sub>opt</sub> *default-argument*<sub>opt</sub>\r\n\r\n>*record-property-name*:\r\n&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;`:` *identifier*\r\n\r\n>*class-body*:\r\n&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;`{` *class-member-declarations*<sub>opt</sub> `}`\r\n&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;`;`\r\n</em>\r\n\r\nEach *record-parameter* in a class declaration defines a property of that name in the declaration space (§3.3) of that class. If a *record-property-name* is present, the *identifier* before the colon names the constructor parameter and the parameter of `operator is`, and the *identifier* after the colon names the corresponding property. If a *record-property-name* is absent, the *identifier* of the *record-parameter* names both the parameter and the property. The property so declared may not have the same name as another parameter, a type parameter or a member declared in that class.\r\n\r\nBecause record classes are often useful without the need for any members explicitly declared in a class-body, we modify the syntax of the class declaration to allow a body to be simply a semicolon terminator.\r\n\r\nA class (struct) declared with the *record-parameters* is called a record class (struct).\r\n\r\n### 1.1 <a name=\"1.1\" />Members of a record type\r\n\r\nIn addition to the members declared in the *class-body*, a record type has the following additional members:\r\n\r\n#### 1.1.1 <a name=\"1.1.1\" />Primary Constructor\r\n\r\nA record type has a `public` constructor whose signature corresponds to the value parameters of the type declaration. This is called the *primary constructor* for the type. A default constructor is not provided for a record type. At runtime the primary constructor\r\n\r\n* initializes compiler-generated backing fields for the properties corresponding to the value parameters (if these properties are compiler-provided; [see 1.1.2](#1.1.2)); then\r\n\r\n* executes the instance field initializers appearing in the *class-body*; and then\r\n\r\n* invokes a base class constructor:\r\n\r\n\t* If there are arguments in the *class-base* specification, a base constructor selected by overload resolution with these arguments is invoked;\r\n\r\n\t* Otherwise a base constructor is invoked with no arguments.\r\n\r\n#### <a name=\"1.1.2\" />1.1.2 Properties\r\n\r\nFor each value parameter of a record class declaration there is a corresponding `public` property member whose name and type are taken from the value parameter declaration. If the *record-property-name* appears in the declaration, it provides the name of the property; otherwise the property’s name is the name of the parameter. If this `public` property is not explicitly declared within the *class-body*, then the compiler produces the implementation as follows:\r\n\r\n* A `private` `readonly` field is produced as a backing field for a `readonly` property. Its value is initialized with the value of the corresponding primary constructor parameter.\r\n\r\n* The property is implemented to return the value of the backing field.\r\n\r\n#### <a name=\"1.1.3\" />1.1.3 Object Methods\r\n\r\nCompiler-generated implementations of the methods `object.GetHashCode()` and `object.Equals(object)` are produced by the compiler unless provided by the user.\r\n\r\n#### <a name=\"1.1.4\" />1.1.4 `operator is`\r\n\r\nA record class has a compiler-generated `public static bool operator is` unless one with any signature is provided by the user. Its first parameter is the record type, and each subsequent parameter is an `out` parameter of the same name and type as the corresponding parameter of the record type.\r\n\r\n#### <a name=\"1.1.5\" />1.1.5 Example\r\n\r\nFor example, the record class declaration:\r\n\r\n```\r\npublic class Cartesian(double x: X, double y: Y);\r\n```\r\n\r\nIs translated into:\r\n\r\n```\r\npublic class Cartesian\r\n{\r\n\tprivate readonly double $X;\r\n\tprivate readonly double $Y;\r\n\tpublic Cartesian(double x, double y)\r\n\t{\r\n\t\tthis.$X = x;\r\n\t\tthis.$Y = y;\r\n\t}\r\n\tpublic double X { get { return this.$X; } }\r\n\tpublic double Y { get { return this.$Y; } }\r\n\tpublic static bool operator is(Cartesian c, out double x, out double y)\r\n\t{\r\n\t\tx = c.X;\r\n\t\ty = c.Y;\r\n\t\treturn true;\r\n\t}\r\n\toverride public bool Equals(object obj)\r\n\t{\r\n\t\tif (obj.GetType() != typeof(Cartesian)) return false;\r\n\t\tvar $o = obj as Cartesian;\r\n\t\treturn object.Equals(X, $o.X) && object.Equals(Y, $o.Y);\r\n\t}\r\n\toverride public int GetHashCode()\r\n\t{\r\n\t\tint $v = 1203787;\r\n\t\t$v = ($v * 28341) + X?.GetHashCode().GetValueOrDefault();\r\n\t\t$v = ($v * 28341) + Y?.GetHashCode().GetValueOrDefault();\r\n\t}\r\n\toverride public string ToString()\r\n\t{\r\n\t\treturn new System.Text.StringBuilder()\r\n\t\t\t.Append(“Cartesian(X: “)\r\n\t\t\t.Append(X)\r\n\t\t\t.Append(“, Y: ”)\r\n\t\t\t.Append(Y)\r\n\t\t\t.Append(“)”)\r\n\t\t\t.ToString();\r\n\t}\r\n}\r\n```\r\n\r\n### <a name=\"1.2\" />1.2 Class-base specification\r\n\r\nThe initial part of the current §10.1.4 is augmented as follows:\r\n\r\n> A class declaration may include a *class-base* specification, which defines the direct base class of the class and the interfaces directly implemented by the class.\r\n\r\n> *class-base*:\r\n&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;`:` *class-type* *arguments*<sub>opt</sub>\r\n&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;`:` *interface-type-list*\r\n&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;`:` *class-type* *arguments*<sub>opt</sub> , *interface-type-list*\r\n\r\n> arguments:\r\n&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;`(` *argument-list*<sub>opt</sub> `)`\r\n\r\n> The class-base of a class-declaration is only permitted to have arguments if the class declaration has *record-parameters*. The arguments implicitly act as arguments to the base call of the primary constructor.\r\n\r\n### <a name=\"1.3\" />1.3 Constructor Declarations\r\n\r\nUser-declared constructors or a record type may not chain to a base constructor.\r\n\r\n### <a name=\"1.4\" />1.4 Scope of class value parameters.\r\n\r\nClass value parameters are in scope in the instance field initializers of the class and in the arguments of the *class-base* specification (where they shadow the corresponding properties). Elsewhere in the class the names of the class value parameters refer to the corresponding properties.\r\n\r\n## <a name=\"2\" />2 A record type name is invocable [optional]\r\n\r\nWe amend the second paragraph of §7.4 (Member Lookup) as follows:\r\n\r\n> If a member is a method or event, or if it is a constant, field or property of either a delegate type or the type dynamic, or if it is a record type, then the member is said to be invocable.\r\n\r\nA corresponding change is made to §7.6.5 (Invocation expressions): An invocation expression of the form\r\n\r\n&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;*type* `(` *argument-list*<sub>opt</sub> `)`\r\n\r\nwhere *type* is a record type has the same meaning as the corresponding invocation expression\r\n\r\n&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;`new` *type* `(` *argument-list*<sub>opt</sub> `)`\r\n\r\n## <a name=\"3\" />3 User-defined operator is\r\n\r\nA user-declared `operator is` may be declared either to provide an implementation to replace the otherwise compiler-generated operator, or to extend the pattern matching capabilities. Such a method is invoked by the `is` operator or a *switch-statement* with a *recursive-pattern*.\r\n\r\nFor example, suppose we have a type representing a Cartesian point in 2-space:\r\n\r\n```\r\npublic record class Cartesian(double X, double Y);\r\n```\r\n\r\nWe may sometimes think of them in polar coordinates:\r\n\r\n```\r\npublic static class Polar\r\n{\r\n\tpublic static bool operator is(Cartesian c, out double R, out double Theta)\r\n\t{\r\n\t\tR = Math.Sqrt(c.X*c.X + c.Y*c.Y);\r\n\t\tTheta = Math.Atan2(c.Y, c.X);\r\n\t\treturn c.X != 0 || c.Y != 0;\r\n\t}\r\n}\r\n```\r\n\r\nAnd now we can operate on `Cartesian` values using polar coordinates\r\n\r\n```\r\nvar c = Cartesian(3, 4);\r\nif (c is Polar(var R, *)) Console.WriteLine(R);\r\n```\r\n\r\nWhich prints `5`.\r\n\r\n## <a name=\"4\" />4 Is Expression\r\n\r\nThe `is` operator is extended to test an expression against a *pattern*.\r\n\r\n>*relational-expression*:\r\n&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;*relational-expression* `is` *complex-pattern*\r\n&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;*relational-expression* `is` *type*\r\n\r\nIt is a compile-time error if *e* does not designate a value or does not have a type.\r\n\r\nEvery *identifier* of the pattern introduces a new local variable into the enclosing scope that is *definitely assigned* after the `is` operator is `true` (i.e. *definitely assigned when true*).\r\n\r\n## <a name=\"5\" />5 Patterns\r\n\r\nPatterns are used in the `is` operator and in a *switch-statement* to express the shape of data against which incoming data is to be compared. Patterns may be recursive so that subparts of the data may be matched against subpatterns.\r\n\r\n>*complex-pattern*:\r\n&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;*constant-pattern*\r\n&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;*type* *identifier*\r\n&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;*recursive-pattern*\r\n&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;*recursive-pattern* *identifier*\r\n&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;*property-pattern*\r\n&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;*property-pattern* *identifier*\r\n\r\n>*recursive-pattern*:\r\n&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;*type* `(` *subpattern-list*<sub>opt</sub> `)`\r\n\r\n>*property-pattern*:\r\n&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;*type* `{` *property-pattern-list* `}`\r\n\r\n>*property-pattern-list*:\r\n&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;*identifier* `is` *pattern*\r\n&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;*identifier* `is` *pattern* `,` *property-pattern-list*\r\n\r\n>*subpattern-list*:\r\n&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;*subpattern*\r\n&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;*subpattern-list* `,` *subpattern*\r\n\r\n>*subpattern*:\r\n&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;*argument-name*<sub>opt</sub> *pattern*\r\n\r\n>*pattern*:\r\n&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;*simple-pattern*\r\n&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;*complex-pattern*\r\n\r\n>*simple-pattern*:\r\n&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;*wildcard-pattern*\r\n&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;`var` *identifier*\r\n\r\n>*wildcard-pattern*:\r\n&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;`*`\r\n\r\n>*constant-pattern*:\r\n&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;*constant-expression*\r\n\r\n### <a name=\"5.1\" />5.1 Type Pattern\r\n\r\nThe type pattern both tests that an expression is of a given type and casts it to that type if the test succeeds. This introduces a local variable of the given type named by the given identifier. That local variable is *definitely assigned* when the is operator is true.\r\n\r\n>*complex-pattern*:\r\n&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;*type* *identifier*\r\n\r\nThe runtime semantic of this expression is that it tests the runtime type of the left-hand *relational-expression* operand against the *type* in the pattern. If it is of that runtime type (or some subtype), the result of the `is operator` is `true` and the local variable is assigned the value of the left-hand operand.\r\n\r\nCertain combinations of static type of the left-hand-side and the given type are considered incompatible and result in compile-time error. A value of static type `E` is said to be *pattern compatible* with the type `T` if there exists an identity conversion, an implicit reference conversion, a boxing conversion, an explicit reference conversion, or an unboxing conversion from `E` to `T`. It is a compile-time error if an expression of type `E` is not pattern compatible with the type in a type pattern that it is matched with.\r\n\r\nThe type pattern is useful for performing runtime type tests of reference types, and replaces the idiom\r\n\r\n```\r\nvar v = expr as Type;\r\nif (v != null) { // code using v }\r\n```\r\n\r\nWith the slightly more concise\r\n\r\n```\r\nif (expr is Type v) { // code using v }\r\n```\r\n\r\nThe type pattern can be used to test values of nullable types: a value of type `Nullable<T>` (or a boxed `T`) matches a type pattern if the value is non-null and the type is `T` or some base type or interface of `T`. For example, in the code fragment\r\n\r\n```\r\nint? x = 3;\r\nif (x is int v) { // code using v }\r\n```\r\n\r\nThe condition of the `if` statement is `true` at runtime and the variable `y` holds the value `3` inside the block.\r\n\r\n### <a name=\"5.2\" />5.2 Constant Pattern\r\n\r\nA constant pattern tests the runtime value of an expression against a constant value. The constant may be any constant expression, such as a literal, the name of a declared `const` variable, or an enumeration constant.\r\n\r\nAn expression *e* matches a constant pattern *c* if `object.Equals(e, c)` returns `true`.\r\n\r\n>*constant-pattern*:\r\n&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;*constant-expression*\r\n\r\nIt is a compile-time error if the static type of *e* is not *pattern compatible* with the type of the constant.\r\n\r\n[NOTE: we plan to revise this section to allow equal values of distinct integral types to match]\r\n\r\n### <a name=\"5.3\" />5.3 Var Pattern\r\n\r\nAn expression *e* matches the pattern `var identifier` always. In other words, a match to a var pattern always succeeds. At runtime the value of *e* is bounds to a newly introduced local variable. The type of the local variable is the static type of *e*.\r\n\r\n### <a name=\"5.4\" />5.4 Wildcard Pattern\r\n\r\nAn expression *e* matches the pattern `*` always. In other words, every expression matches the wildcard pattern.\r\n\r\n### <a name=\"5.5\" />5.5 Recursive Pattern\r\n\r\nA recursive pattern enables the program to invoke an appropriate `operator is`, and (if the operator returns `true`) perform further pattern matching on the values that are returned from it.\r\n\r\n>*recursive-pattern*:\r\n&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;*type* `(` *subpattern-list*<sub>opt</sub> `)`\r\n\r\nGiven a match of an expression *e* to the pattern *type* `(` *subpattern-list*<sub>opt</sub> `)`, a method is selected by searching in *type* for accessible declarations of `operator is` and selecting one among them using *match operator overload resolution* (see §[5.5.1](#5.5.1)). It is a compile-time error if the expression *e* is not *pattern compatible* (see §[5.1](#5.1)) with the type of the first argument of the selected operator.\r\n\r\nAt runtime, the value of the expression is tested against the type of the first argument as in a type pattern. If this fails then the recursive pattern match fails and the result is `false`. If it succeeds, the operator is invoked with fresh compiler-generated variables to receive the `out` parameters. Each value that was received is matched against the corresponding *subpattern* (see §[5.5.1](#5.5.1)), and the match succeeds if all of these succeed. The order in which subpatterns are matched is not specified, and a failed match may not match all subpatterns.\r\n\r\nIf a *subpattern* has an *argument-name*, then every subsequent *subpattern* must have an *argument-name*.\r\n\r\n#### <a name=\"5.5.1\" />5.5.1 Property Pattern\r\n\r\nA property pattern enables the program to recursively match values extracted by the use of properties.\r\n\r\n>*property-pattern*:\r\n&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;*type* `{` *property-pattern-list* `}`\r\n>*property-pattern-list*:\r\n&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;*identifier* `is` *pattern*\r\n&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;*identifier* `is` *pattern* `,` *property-pattern-list*\r\n\r\nGiven a match of an expression *e* to the pattern *type* `{` *property-pattern-list* `}`, it is a compile-time error if the expression *e* is not *pattern compatible* with the type *T* designated by *type*.\r\n\r\nAt runtime, the expression is tested against *T*. If this fails then the property pattern match fails and the result is `false`. If it succeeds, then each of the identifiers appearing on the left-hand-side of its *property-pattern-list* must designate a readable property or field of *T*. Each such field or property is matched against its corresponding pattern, and the result of the whole match is `false` only if the result of any of these is `false`. The order in which subpatterns are matched is not specified, and a failed match may not match all subpatterns\r\n\r\n## <a name=\"6\" />6 Switch Statement\r\n\r\nThe `switch` statement is extended to select for execution the first block having an associated pattern that matches the *switch expression*.\r\n\r\n>switch-label:\r\n&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;`case`  *complex-pattern* `:`\r\n&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;`default :`\r\n\r\n[TODO: we need to explain the interaction with definite assignment here.]\r\n\r\nThe order in which patterns are matched is not defined. A compiler is permitted to match patterns out of order, and to reuse the results of already matched patterns to compute the result of matching of other patterns.\r\n\r\nIn some cases the compiler can prove that a switch section can have no effect at runtime because its pattern is subsumed by a previous pattern. In these cases a warning may be produced. [TODO: these warnings should be mandatory and we should specify precisely when they are produced.]\r\n\r\nThe scope of a variable declared in a pattern of a *switch-label* is the containing *switch-section*.\r\n\r\n## <a name=\"7\" />7 Some Possible Optimizations\r\n\r\nThe compilation of pattern matching can take advantage of common parts of patterns. For example, if the top-level type test of two successive patterns in a *switch-statement* is the same type, the generated code can skip the type test for the second pattern.\r\n\r\nWhen some of the patterns are integers or strings, the compiler can generate the same kind of code it generates for a switch-statement in earlier versions of the language.\r\n\r\nFor more on these kinds of optimizations, see [[Scott and Ramsey (2000)]](http://www.cs.tufts.edu/~nr/cs257/archive/norman-ramsey/match.pdf \"When Do Match-Compilation Heuristics Matter?\").\r\n\r\nIt would be possible to support declaring a type hierarchy closed, meaning that all subtypes of the given type are declared in the same assembly. In that case the compiler can generate an internal tag field to distinguish among the different subtypes and reduce the number of type tests required at runtime. Closed hierarchies enable the compiler to detect when a set of matches are complete. It is also possible to provide a slightly weaker form of this optimization while allowing the hierarchy to be open.\r\n\r\n## <a name=\"8\" />8 Some Examples of Pattern Matching\r\n\r\n### <a name=\"8.1\" />8.1 Is-As\r\n\r\nWe can replace the idiom\r\n\r\n```cs\r\nvar v = expr as Type;\t\r\nif (v != null) {\r\n    // code using v\r\n}\r\n```\r\n\r\nWith the slightly more concise and direct\r\n\r\n```cs\r\nif (expr is Type v) {\r\n    // code using v\r\n}\r\n```\r\n\r\n### <a name=\"8.2\" />8.2 Testing nullable\r\n\r\nWe can replace the idiom\r\n\r\n```cs\r\nType? v = x?.y?.z;\r\nif (v.HasValue) {\r\n    var value = v.GetValueOrDefault();\r\n    // code using value\r\n}\r\n```\r\n\r\nWith the slightly more concise and direct\r\n\r\n```cs\r\nif (x?.y?.z is Type value) {\r\n    // code using value\r\n}\r\n```\r\n\r\n### <a name=\"8.4\" />8.4 Arithmetic simplification\r\n\r\nSuppose we define a set of recursive types to represent expressions:\r\n\r\n```cs\r\nabstract class Expr;\r\nclass X() : Expr;\r\nclass Const(double Value) : Expr;\r\nclass Add(Expr Left, Expr Right) : Expr;\r\nclass Mult(Expr Left, Expr Right) : Expr;\r\nclass Neg(Expr Value) : Expr;\r\n```\r\n\r\nNow we can define a function to compute the (unreduced) derivative of an expression:\r\n\r\n```cs\r\nExpr Deriv(Expr e)\r\n{\r\n  switch (e) {\r\n    case X(): return Const(1);\r\n    case Const(*): return Const(0);\r\n    case Add(var Left, var Right):\r\n      return Add(Deriv(Left), Deriv(Right));\r\n    case Mult(var Left, var Right):\r\n      return Add(Mult(Deriv(Left), Right), Mult(Left, Deriv(Right)));\r\n    case Neg(var Value):\r\n      return Neg(Deriv(Value));\r\n  }\r\n}\r\n```\r\n\r\nAn expression simplifier demonstrates recursive patterns:\r\n\r\n```cs\r\nExpr Simplify(Expr e)\r\n{\r\n  switch (e) {\r\n    case Mult(Const(0), *): return Const(0);\r\n    case Mult(*, Const(0)): return Const(0);\r\n    case Mult(Const(1), var x): return Simplify(x);\r\n    case Mult(var x, Const(1)): return Simplify(x);\r\n    case Mult(Const(var l), Const(var r)): return Const(l*r);\r\n    case Add(Const(0), var x): return Simplify(x);\r\n    case Add(var x, Const(0)): return Simplify(x);\r\n    case Add(Const(var l), Const(var r)): return Const(l+r);\r\n    case Neg(Const(var k)): return Const(-k);\r\n    default: return e;\r\n  }\r\n}\r\n```\r\n\r\n### <a name=\"8.5\" />8.5 Roslyn diagnostic analyzers\r\n\r\nMuch of the Roslyn compiler code base, and client code written to use Roslyn for producing user-defined diagnostics, could have its core logic simplified by using syntax-based pattern matching.\r\n\r\n### <a name=\"8.6\" />8.6 Cloud computing applications\r\n\r\n[NOTE: This section needs much more explanation and examples.]\r\n\r\n* Records are very convenient for communicating data in a distributed system (client-server and server-server).\r\n  It is also useful for returning multiple results from an async method.\r\n* \"Views\", or user-written operator \"is\", is useful for treating, for example,\r\n json as if it is an application-specific data structure. Pattern matching is very convenient for\r\n dispatching in an actors framework.\r\n\r\n## <a name=\"A\" />A Open Issues\r\n\r\n*\tPattern matching with anonymous types.\r\n*\tPattern matching with arrays.\r\n*\tPattern matching with List<T>, Dictionary<K, V>\r\n*\tAdd `when (expression)` filter on switch cases.\r\n*\tShould the parameters be implicitly `readonly`?\r\n*\tCan attributes be placed independently on the symbols resulting from a parameter in\r\n \tthe class/struct declaration? In general, attributes could go on any of\r\n\t*\tclass value parameter\r\n\t*\tthe backing field\r\n\t*\tthe property\r\n\t*\tthe property’s get method\r\n*\tWe need detailed specifications for `Equals`, `GetHashCode`, and `ToString`.\r\n*\tHow, if at all, should default value parameters impact the shape of `operator is`?\r\n*\tHow should the type `dynamic` interact with pattern matching?\r\n*\tIn what situations should the compiler be required by specification to warn about a match that must fail. E.g. switch on a `byte` but case label is out of range?\r\n*\tShould there be a way to declare that a *switch-statement* is intended to be complete?\r\n*\tShould it be possible to combine a recursive pattern and a property pattern into a single pattern, like `Point(int x, int y) { Length is 5 }` ?\r\n*\tAdd support for `IEquatable<T>` to the code generated when type parameters are given?\r\n*\tClean up the terminology, enabling record classes to apply equally to structs too.\r\n*\tThe specification should allow a pattern that is an integral constant expression\r\n \tto be used to match that value of any integral type. \r\n\r\n## <a name=\"B\" />B Change Log\r\n\r\n*\t2014-08-07 Changed “pattern class” to “record class”.\r\n*\t2014-08-08 Added record-property-name to optionally name the property separately from the parameter. \r\n*\t2014-08-16 This document does not indicate Microsoft’s intent to include these features in any future version of the language.\r\n*\t2014-09-04 Clarified that the generated properties are readonly, but the hand-written ones need not be.\r\n*\t2014-09-08 Added the “property” pattern.\r\n*\t2015-02-02 Converted to markdown for posting on github\r\n*\t2015-02-01 Changed the implementation of `object.Equals` to respect inheritance.\r\n*\t2015-02-01 Removed the `record` keyword on a record type declaration.\r\n    The new behavior is now keyed on the presence of the parameter list."},"comment":{"url":"https://api.github.com/repos/dotnet/roslyn/issues/comments/73070799","html_url":"https://github.com/dotnet/roslyn/issues/206#issuecomment-73070799","issue_url":"https://api.github.com/repos/dotnet/roslyn/issues/206","id":73070799,"user":{"login":"Richiban","id":668303,"avatar_url":"https://avatars.githubusercontent.com/u/668303?v=3","gravatar_id":"","url":"https://api.github.com/users/Richiban","html_url":"https://github.com/Richiban","followers_url":"https://api.github.com/users/Richiban/followers","following_url":"https://api.github.com/users/Richiban/following{/other_user}","gists_url":"https://api.github.com/users/Richiban/gists{/gist_id}","starred_url":"https://api.github.com/users/Richiban/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Richiban/subscriptions","organizations_url":"https://api.github.com/users/Richiban/orgs","repos_url":"https://api.github.com/users/Richiban/repos","events_url":"https://api.github.com/users/Richiban/events{/privacy}","received_events_url":"https://api.github.com/users/Richiban/received_events","type":"User","site_admin":false},"created_at":"2015-02-05T15:59:45Z","updated_at":"2015-02-05T15:59:45Z","body":"I propose declaring record classes as such: \r\n\r\n```\r\npublic record class Person\r\n{\r\n    string Name { get; set; }\r\n    DateTime DoB { get; }\r\n \r\n    bool IsRobot { get; set; } = false;\r\n}\r\n```\r\n\r\nSeveral things to note:\r\n* the lack of visibility modifiers. Like an interface, everything is public in a record class\r\n* Members can be mutable or immutable. Both types need to be intialised when instantiating the record type\r\n* Members can be optional. This is signified by giving a default value in the type definition.\r\n \r\nThe advantage of this is that records syntax is the same as the class syntax in C# 6. The `record` keyword just tells you that the constructor, equals, ToString and GetHashCode methods are implemented for you.\r\n\r\nI also feel that, when initialising a record, the object initialisation syntax is better than constructor syntax (it plays a lot better with the concept of optional members)."}}