
# C# LDM Notes for Mar 19, 2019

## Agenda

MVP Summit Live LDM w/ Q&A

Topics:

1. Records
2. "Extension interfaces"/roles
3. Macros
4. IAsyncEnumerable
5. "Partially automatic" properties
6. More integration with reactive extensions

## Discussion

We grouped the discussion into topics to try to maintain a bit of shared
state in the discussion.

### Records

*Q: How "extensible" will the design be? Could the user provide some sort of
template that the compiler would implement for their record, more than the
equality and data access features we are initially thinking of?*

We're not clear on what kind of templating we could offer, but there are two
problems we foresee with generalizing the feature:

1. Even simple equality is actually a bit tricky to write and be correct for
   subtyping.
2. Generalized templating is tricky to do in a type safe way. One alternative
   is something like hygenic macros, but we're not willing to go that far in
   the language at the moment. We definitely are not interested in allowing
   for custom syntax forms.

*Q: Do we not want inheritance? If that's the only thing blocking records?*

1. Inheritance isn't the main thing blocking records. It's mostly lack of
   design time to work out the last few issues, namely what the simplest
   syntax means, support for nominal and structural construction, and
   incorporating the design with discriminated unions.

1. We think inheritance is important for "extensible" records and it's hard to
   add later.

*Q: Will record syntax be supported for structs?*

Yes, almost certainly. We're also looking into discriminated unions for structs
as well, although it's more difficult because the size of the struct is more
complicated.

*Q: Deep vs shallow immutability? Value-equality is more natural if there's
deep immutability, since two things which may be value equal originally may
not be so if a nested value is changed, but the top level equality is only
calculated shallowly.*

Not currently on the table, records will only have shallow immutability be
default, if they are immutable by default. We probably have no mechanism
to figure out if equality is broken, either, because the language doesn't
currently have a good way of reasoning about this transitevely.


### Extension interfaces/roles

*Q: Is this duck typing?*

Maybe, it depends on what you mean by duck typing. It's certainly a way
to implement an interface after the type has been defined. One of the
design goals can be phrased, "here's a class, here's an interface, let's make
them fit together", but it's not restricted to what's stated in the class,
because we feel there's often a small gap between the interface and class that
needs to be filled out.

It's also not the case that any type which structurally matches the interface
"magically" implements the interface -- all our current designs are nominal
and explicit. This is partially because it fits with how C# works as a whole,
but also that interface implementation is a CLR language concept that isn't
as loose as some other duck typing designs.

*Q: Constructors on interfaces?*

(Meaning no body, just for the constraint)

It's not currently a part of "static members on interfaces" and it
seems very similar to proposals to extend the `new()` constraint?

When we looked at it in the past we thought the cost/value prop is probably
questionable as a standalone feature, but maybe as part of the broader
interface feature. The biggest mark against it is there's a workaround
of using a delegate that returns the given interface, which generally
works pretty well.


*Q: What scope would the "extension interfaces" be in?*

We'll probably import most of the scoping rules of extension methods.

*Q: What about extension fields? Using ConditionalWeakTable?*

This consequences are subtle and we'll probably favor having the user
do this explicitly if that's what they mean.

*Q: Scala-like "implicit" parameters?*

We looked at it, but we're concerned it may be too subtle.

### General metaprogramming

*Q: Source generators?*

We tried a maximal approach for source generators, but the tooling was not
able to keep up. There may be something here, but we're not going to do
anything until we can guarantee investment across the whole stack.

*Q: Can we skip the tooling?*

There isn't really a difference between generated C# and standard C#, so
there's no clear line to "cut off" the tooling. It's not the author that
we're primarily worried about, it's all of the downstream users, who are
strongly expecting current features to continue to work.

*Q: What are new languages the LDM looks to for ideas?*

We generally look at everything we can find, and the LDM has people with
their own interests, so we tend to have a mix of perspectives.

Some examples:

We've looked at Rust and Go for perf-centric designs and "zero-cost abstraction"
ideas.

We look at Scala for lot's of ideas on merging functional and OO. They're not
necessarily the language we want to be, but they've traveled a lot of the
same ground.

### IAsyncEnumerable

*Q: How does ConfigureAwait/Cancellation work?*

Right now we have ConfigureAwait and WithCancellation methods for
IAsyncEnumerable that allow you to add functionality at the `await foreach`
site, e.g.

`await foreach (var x in iasyncenum.ConfigureAwait(false))`

What we don't currently have a mechanism for is flowing a token from the
`foreach` to the generated awaits in the iterator method. For instance,

```C#
var iasyncenum = IterMethod(token);
await foreach (var x in iasyncenum)
{
    ...
}

IAsyncEnumerable<int> IterMethod(CancellationToken token)
{
    yield return 0;
    token.ThrowIfCancelled();
    await Task.Delay(1);
    yield return 1;
}
```

Note that you can flow a token through manually, but then you must control
calling the iterator and executing the foreach -- there's no way to pass
a new cancellation token during the `await foreach`.

There's some feedback that this could be useful, so we'll take another
look at it.

*Q: Plans to add an ability to await an event?*

We're not quite sure how this would work. In general, libraries have
some support for this pattern, so we don't see a huge need right now.

*Q: Plans to support "partially automatic" properties that let you
access the generated backing field?*

There's been some talk about allowing a field to be declared inside
the property that's only accessible there, e.g.

```C#
public int Property
{
    private int _field;
    get => _field;
    set { _field = value; }
}
```

We haven't had a full discussion about this idea yet.

### More integration with Reactive Extensions in the language?

For instance, IObservable?

Our current view is that `IAsyncEnumerable` is the mechanism to link Rx into
the language. The problem with stronger language integration is that it will
require configuration for various buffering/back-pressure options. We think
that's better solved by library authors and hope that the current design
will strike a good balance.
