# C# Language Design Meeting for Apr 22, 2024

## Agenda

- [Effect of language version on overload resolution in presence of `params` collections](#effect-of-language-version-on-overload-resolution-in-presence-of-params-collections)
- [Partial type inference: '_' in method and object creation type argument lists](#partial-type-inference-_-in-method-and-object-creation-type-argument-lists)

## Effect of language version on overload resolution in presence of `params` collections

(https://github.com/dotnet/csharplang/issues/8061)

Issues were encountered when earlier C# versions were specified.  For example, the runtime team added `params ReadOnlySpan<object>` and users that combined .NET 9 and C# 12, such as with the `.csproj` fragment that follows, received an error:

```dotnetcli
<LangVersion>12</LangVersion>
<TargetFramework>net9.0</TargetFramework>
```

> The feature 'params collections' is currently in Preview and unsupported. To use Preview features, use the 'preview' language version.

This happens because the changes we made to overload resolution to prefer params `ReadOnlySpan<T>` are unconditional but using the feature is guarded by `LangVersion`.

Looking at how we have handled guarding other features on `LangVersion` finds variations where different features have been handled differently and features have been handled differently at different points in C# history.

A primary reason for `LangVersion` was included in Roslyn is to support teams where some members are on a later version of the compiler - for example because they are using a later version of Visual Studio. 

For at least much of the Roslyn history, if using a feature would cause an error if used with an earlier compiler (SDK/VS version), then consumption was not supported. Otherwise it was.

Available options for handling overload resolution in this case are given below.

#### Ignore language version on consumption

There are concerns on ignoring language version on consumption because of how much it is tied to collection expressions. We expect the compiler would inject C# 11+ code patterns into C# 10 (or early) code bases which would not be expecting collection expressions.

#### Guard applicable function member changes on LangVersion

This approach would result in the new rules only applying to C# 13 and above.

_Applicable function member_ refers to expanding `params` at the callsite to act as a collection expression.

You could still explicitly call the method, but it would not be chosen during overload resolution for `params`.

#### Guard all overload changes on LangVersion

This is a variation of the previous option.

### Breaking Changes

While selecting a different overload is a breaking change,  we sometimes take this kind of change.

If code starts working in the C# 13 compiler's version of C# 11, that can create an issue in teams. And also, if the selected overload changes when you do not change your compiler, but upgrade your language version and call a different overload, that's a break.

Additional language version guards in the compiler add complexity and increasing the test matrix. But not applying the guard means that if a user upgrades their compiler they could see different overload resolution, even if they continue to use the same lower version of C#. Since we have said we will evolve the behavior of collection expressions to make them better, you could get a change in code (although not a semantic change) every year.

### Conclusion

We will guard based on language version - approach [Guard applicable function member changes on LangVersion](#guard-applicable-function-member-changes-on-langversion).

## Partial type inference: '_' in method and object creation type argument lists

(https://github.com/dotnet/csharplang/pull/7582)

### Discussion

We reviewed a proposal for skipping inferrable type arguments in the type argument list for invocation expressions and object creation expressions.
 
In addition to type arguments, there are other potential uses (more in the proposal):

```csharp
// This code is to show the possible application
// and is not an indication of syntax.
G<_,>
_[] // arrays
_? // nullable types
```

### Possible syntax

```csharp
- `_` (underscore)
- `var`
- `` (empty)
- `..`
- `*`
- `__`
```

### Conclusion

We will continue to explore top level type inference.

It is too early to make a decision on syntax, but we lean to using `var` as the most semantically correct.

To preserve this space, we may begin disallowing `_` as a type name. If you wish to use it as a type name, you would need to prefix: `@_`.
