
# C# Language Design Notes for March 4th, 2019

## Agenda

1. Nullable user studies
2. Interpolated string and string.Format optimizations

## Discussion

### The 'default loophole'

`var y = default(SomeStructWithNonNullableFields);`

For the above, no warning is produced. The same is true for other `default`
expressions. Is that OK?

**Conclusion**

Let's continue to track the nullability of the fields and not produce a
warning. If we were to produce a warning it seems likely that we would
produce warnings that are fundamentally unactionable because the user doesn't
control the struct definition.

### User study for nullable design

Today we went over the results from some user studies which simulated
upgrading a code base with the non-nullable reference types design enabled.

There were 5 sessions, with two simple, but non-trivial, code bases:

1. Telegram bot API
2. Jil, a JSON serializer

Problems: 

- People had a fair amount of problems with member definitions, rather than
  bodies
    - We haven't published much information on how nullable interacts with
      definitions

    - Interface implementation and overriding are hard to fix since there
    are multiple places that need to change for every nullability change

- Object initializer pattern is a persistent problem and the warnings
  don't seem to be providing much value

- Constructor chaining is also a problem, where fields are piecewise initialized

  - Worse, when looking at the diagnostic, it was hard to get to the member,
    but when you're at the member, it's hard to verify this one was the
    problem because the diagnostic also does not occur

  - Almost everyone expected the warnings to be on the field/property

- Nullable value types are a problem because they assumed that the problems
  were in nullable reference types, but the problems/solutions were subtly
  different

- Diagnostic quality: generics were confusing, especially with tuples

- Code fixes

  - People definitely want code fix to/from a nullable reference

  - They want a "fix-all" but it's not clear what that is

    - Some people wanted to see all the warnings, but then narrow down,
      especially via a code fix

- Some people looked at the process as "satisfying the compiler" and others
  looking at "code hygiene" or "possible bugs"

   - There were at least a few null-safety bugs and no one found them
     in the time allotted, but probably would have

   - People who used the feature for overall code hygiene were more
     excited about using the feature

### `params` and string interpolation

We discussed a new proposal for improving the performance of certain
string.Format calls and interpolated string expressions.

Proposal: https://github.com/dotnet/csharplang/blob/master/proposals/format.md

Summary:

Using certain APIs, especially `params` and `string.Format`, can be a source
of large performance problems. For certain projects (MSBuild) that are
"string manipulation" programs, this can even be the main performance
bottleneck for those programs.

Unfortunately, these APIs are also very convenient and, in many cases, the
preferred way of accessing certain string manipulation functionality in the
.NET framework. We'd like it if these features could be less heavyweight.

Proposals:

1. Allow `params` to have any of the types `Span<T>/ReadOnlySpan<T>/IEnumerable<T>`

Advantages:

- The callee cannot stash the parameter, so we can re-use an allocation

    - Sometimes users do this themselves because it's demonstrably more efficient

Consequences:

Overload resolution needs to change. New tie breaking rules:

- `ReadOnlySpan<T>`

- `Span<T>`

- `T[]`

- `IEnumerable<T>`

2. Allow any standard `Format` overload resolution for interpolated strings

This feature builds on (1). If interpolated strings could use new `Format`
overloads that have `ReadOnlySpan<T>` arguments, interpolated strings could
share in the performance improvements.

3. `ValueFormattableString`

Support new `ValueFormattableString` type as a target of a string
interpolation.

This would be a breaking change when people upgrade to the new framework with
the new type, but the older compiler always chooses the `string` overload (because
it doesn't understand `ValueFormattableString`) and whenever they upgrade the
compiler the call suddenly changes to `ValueFormattableString`. If those two
methods do anything different, that would be a breaking change.

This feature also does not support using a custom type instead of
`ValueFormattableString`. That could be desirable for a number of different
scenarios, but would probably make the backwards compatibility constraints
even more difficult.

We should carefully evaluate the tradeoffs in this feature and see what we
can do to enable the most scenarios without taking unacceptable breaks.

3. `stackalloc` the `Span` for `params`

It's not possible for C# to generally predict whether or not it's OK to
stackalloc arguments. We're interested in enabling this functionality if
provided with a "maybe stackalloc" helper from the runtime, and we'd like to
keep that possibility open, but we will not do anything here until such a
feature is available.