
# C# LDM for Nov. 18th, 2019

## Agenda

1. More patterns

## Discussion

### More patterns

Parenthesized patterns:

- What about ambiguity with a potential 1-tuple pattern?

    - There was a previous ambiguity here with a parenthesized constant expression,
      so matching a 1-tuple pattern requires resolving ambiguity, for example by adding
      tuple names: `x is (Item1: var tupleVal)`

Relational patterns:

We don't love the syntax. The problem is really that we're using a binary operator in
a unary context. On the other hand, it's useful in that it's easy to adjust for closed
or open bounds by adjusting the inclusiveness of the operator.

The other shaky part of the syntax is support for user-defined operators. One of the
fundamental parts of pattern matching is that the semantics are well-understood, meaning
that the switch expression expects certain things must be true, like that checks must return
the same value for the same inputs and can be called any number of times. We have a few patterns
that execute user-defined code, but it seems more likely that they're usually safe (property
getters and Deconstruct).

For `==` and `!=` specifically, they seem redundant and likely to cause confusion when there is a
user-defined operator that is not supported. Consensus is to remove support in relational patterns.

The other confusing part is conversion, where the input type does not statically contain a built-in
the binary operator. For instance,

```C#
object o = (short)1;
_ = o switch
{
    < 3 => 0, // This would be false, since `o` is a short, not an int, and the
              // unconverted '3' is an `int`
};
```

This is already how constant patterns work, so there may be some confusion here already, but we're
worried about broadening the problem by adding the `not` pattern in combination with the relational
operators. For example, if you match `not < 3`, this would evaluate to true, but not because the
value is not less than three, but because it is not an int. This would mean that `>= 3` and `not < 3`
would be different, since the type check can play into the check.

However, we don't have any better approaches, and the hope is that this will be a relatively rare
occurrence. If the input pattern has a statically known built-in operator this would not be a concern.

The proposal states that the input type of the expression must contain a conversion that is not a boxing
conversion. However, we do support constant pattern checks for unconstrained type parameters, so we
need to change the proposal to allow unconstrained type parameters as well.

### Pattern combinators

The proposal contains three breaking changes:

    - `not` is considered a type in C# 8 and a pattern in C# 9.

    - `and` and `or` are allowed as variable names in C# 8, but are pattern combinators in C# 9

An important question is whether these are allowed and how they are breaking. Changing behavior is
probably a bridge too far. We would consider providing an error in the old scenarios and forcing
disambiguation.

We'll need more discussion on the breaking changes and how we can mitigate them.
