3.2 KiB
3.2 KiB
C# Design Meeting 2015-03-25
Discussion thread for these notes can be found at https://github.com/dotnet/roslyn/issues/1572.
These are notes that were part of a presentation on 2015-03-25 of a snapshot of our design discussions for C# 7 and VB 15. The features under discussion are described in detail in #206 and elsewhere.
Records
Changes since Semih Okur's work:
- Remove
record
modifier with
expressions (#5172)- Working on serialization
Working proposal resembles Scala case classes with active patterns.
class Point(int X, int Y);
- defines a class (struct) and common members
- constructor
readonly
properties- GetHashCode, Equals, ToString
- operator== and operator!= (?)
- Pattern-matching decomposition operator
- an association between ctor parameters and properties
- Any of these can be replaced by hand-written code
- Ctor-parameter and property can have distinct names
Use Cases
- Simplifies common scenarios
- Simple immutable user-defined data types
- Roslyn Syntax Trees, bound nodes
- Over-the-wire data
- Multiple return values
With expressions
Illustrates an example of the value of having parameter-property association.
Given
struct Point(int X, int Y);
Point p = ...
the expression
p with { Y = 4 }
is translated to
new Point(p.X, 4)
Open issues
- Closed hierarchy (and tag fields)
- Readonly
- Parameter names
- Can you opt out of part of the machinery?
- Serialization (in all of its forms)
- Construction and decomposition syntax
Pattern Matching
Sources of Inspiration
- Scala
- F#
- Swift
- Rust
- Erlang
- Nemerle
A pattern-matching operation
- Matches a value with a pattern
- Either succeeds or fails
- Extracts selected values into variables
object x = ...;
if (x is 3) ...
if (x is string s) ...
if (x is Point { X is 3, Y is int y }) ...
if (x is Point(3, int y)) ...
Other aspects
- Patterns defined recursively
- "select" from among a set of pattern forms
- Typically an expression form
- active patterns support interop and user-defined types
switch (o)
{
case 3:
...
break;
case string s:
M(s);
break;
case Point(3, int y):
M(y);
break;
case Point(int x, 4):
M(x);
break;
}
We think we want an expression form too (no proposed syntax yet, but for inspiration):
M(match(e) {
3 => x,
string s => s.foo,
Point(3, int y) => y,
* => null })
Benefits
- Condenses long sequences of complex logic with a test that resembles the shape of the thing tested
Use Cases
- Simplifies common scenarios
- Language manipulation code
- Roslyn
- Analyzers
- Protocol across a wire
Open questions
- How much of the pattern-matching experience do we want (if any)?
- Matching may be compiler-checked for completeness
- May be implemented using tags instead of type tests
- Which types have syntactic support?
- Primitives and string
- Records
- Nullable
- objects with properties
- anonymous types?
- arrays?
- List? Dictionary?
- Tuple<...>?
- IEnumerable?