
# C# LDM Notes for Mar 27, 2019

## Agenda

1. Switch expression syntax

1. Default interface implementations

    1. Reabstraction

    2. Explicit interface abstract overrides in classes

    3. `object.MemberwiseClone()`

    4. `static int P {get; set}` semantics

    5. `partial` on interface methods

2. `?` on unconstrained generic param `T`

## Discussion

### Switch expression syntax

Confirmed that we like

```C#
e switch
{
    a => b,
    c => d,
}
```

### Default interface methods

#### Reabstraction

Implement the interface method with an abstract in an interface, forcing
re-implementation of deriving interfaces.

We previously wanted to see a cost for handling it in the runtime and we
know have a proposal for that: https://github.com/dotnet/coreclr/pull/23313

Given that, do we want to allow reabstraction?

**Conclusion**

Assuming the proposed approach, it seems cheap enough. The only question is
if the metadata approach is one we want to add to metadata. Right now we're
going to say yes to the feature, assuming that the runtime teams can produce
the feature. We also want to put this under the runtime feature flag to
prevent exposure to older compilers. We should also do the same for features
like static members in interfaces.

#### Explicit interface abstract overrides in classes

Allow abstract interface implementions in a class as well? Not an abstract
class method implementing an interface method.

**Conclusion**

No, we don't see any great use cases.

#### Is `object.MemberwiseClone()` accessible in an interface?

In principle, maybe yes, but this member seems particularly problematic.
Let's say protected members of object are not accessible.

#### Is `static int P { get; set; }` is an auto-property with a compiler-generated backing field?

This seems consistent with the idea that `static` means `sealed` by
default, but a little strange given that the same syntax without
`static` implies virtual for instance members.

The main problem will be if we allow `static` virtual/abstract members to be
declared in future versions of the language, where this rule doesn't
necessarily make sense.

**Conclusion**

Let's keep the current semantics for now `static int P {get; set;}` -- this
declares a static auto-property. The same goes for static field-like events.

We may revisit this entire area in the future.

#### Confirm that `partial` implies `private` and no access modifier is permitted?

**Conclusion**

Confirmed.

### Nullable reference types

Right now we don't allow the `?` annotation for type parameters that
we don't know to be non-nullable. There are numerous customer scenarios
where people want to do this and are prohibited.

Proposal: `T?` is similar to the constraint `object?`, where T remains
essentially unconstrained.

```C#
class C<T>
{
    T? M(T p1, T? p2)
    {
        if (p2 != null)
            M(p1, null); // error on the `null` because T may be `int`
        if (p2 != null)
            M(p1, default); // OK, because if T is `int`, default is valid
    }
}
```

The goal is to provide value to the consumer that they must deal with null.

A use case would be

```C#
IEnumerable<T> FilterNull<T>(IEnumerable<T?> e)
{
    foreach (var i in e)
    {
        if (i != null)
        {
            yield return e;
        }
    }
}
```

This would make `T?` a replacement for the `MaybeNullAttribute` and would
provide value for places you could not use the `MaybeNullAttribute`, like
nested inside generic types. Moreover, attributes are not required to be
propagated for overrides or interface implementations, so it's very possible
for implementations to drop requirements of their abstract specification.

**Conclusion**

It does seem like our current approach has significant limitations. We want
to look more closely at the customer scenarios, especially around overriding
and interface implementation to decide what more we want to do.