# C# Language Design Meeting for Jan. 13th, 2021

## Agenda

1. [Global usings](#global-usings)
2. [File-scoped namespaces](#file-scoped-namespaces)

## Quote(s) of the Day

- "You're not yelling at me. You're just wrong."
- "All language rules are arbitrary. Some are just more arbitrary than others."

## Discussion

### Global usings

https://github.com/dotnet/csharplang/issues/3428

Today, we started by looking at a long-standing request in various forms: the ability to create using directives that apply
to an entire project. This is of particular importance now as we solidify our work in relation to the .NET 6 themes, especially
around both beginner scenarios and general ease-of-use. A well-studied problem in teaching a programming language is avoiding
cognitive load, and usings are an ever-present cognitive load in C#, even in simple "Hello, World!" style applications. Either
the teacher says "Ignore the `using` thing for now" or they say "Ignore what the `.`s mean for now", with no ability to hold
off on introducing them. That's not to say teaching `using` isn't necessary, and necessary early in the teaching process; merely
that delaying that introduction from the first second of seeing C# to a day or week into the curriculum can be very helpful in
avoiding overloading newcomers and scaring them off.

While it's an important scenario, beginners aren't the only driving motivation here. .NET 6 is looking at making both beginner
and general scenarios better, and there's an argument that this will help general scenarios as well. Large-sized projects such
as dotnet/roslyn are the exception, not the rule; most .NET projects are smaller and don't have nearly so many moving and
interacting pieces. `using` boilerplate has a bigger impact on these projects, particularly as they tend to use many frameworks
and a custom project SDK (such as ASP.NET). That custom SDK, combined with a feature to allow the SDK to specify global usings
in some manner, can help ease these scenarios and remove unnecessary lines from most files in such solutions. Larger projects
like Roslyn may never use this feature, but Roslyn and projects like it are not the projects that much of our users are actually
writing.

Broadly, there are two possible approaches to this type of feature: CLI flags, specifiable for actual users via the project file,
and a syntax form that allows a user to specify a using should apply to all files. We have an existing proposal for the former
approach, 3428 (linked above), and some spitball ideas for what the latter could look like (perhaps something like
`global using System;`). Both have advantages:

* If these are specified via command line flags, then there is one place to go looking for them: the project file. A syntax form
would be potentially able to be spread out among multiple files. It is would be possible to spread these out across multiple
props files if users wanted to, but the types of projects that use these features are likely rarer than the types of projects
that use multiple C# files. Tooling could certainly help here, such as creating a new node in the project explorer to list all
the global usings for a project, but we do still need to consider cases where code is not viewed in an IDE such as on GitHub.
* We have a number of long-standing requests for having global using aliases. While these can be accomplished via the CLI flag
proposal, it would be significantly easier and more accessible to users if they had a syntax form of doing so.
* A syntax form would allow participation from source generators. We're somewhat split on whether that's a good thing or not.
* A syntax form might be a barrier to potential abilities to do things like `dotnet run csfile` in the future: where would the
syntax form live? An ethereal temp file, or a hardcoded part of the SDK?

#### Conclusion

We seem to have unanimous agreement here that the design space is interesting, and we would like a feature to address the issues
discussed above. We're much more split on the potential approaches, however, and need to explore the space more in depth.

### File-scoped namespaces

https://github.com/dotnet/csharplang/issues/137

We're picking back up on the discussion from [last week](LDM-2021-01-05.md#file-scoped-namespaces), which is around how
restrictive we should be in permitted mixing and matching of multiple namespace statements and combination with traditional
namespace directives. An important point to acknowledge is that, regardless of what decision we make here, Roslyn is going to
have to do something to understand what multiple namespace directives in a file means because it will encounter that code at
some point, regardless of whether it's valid or not, and will have to do its level best to make a guess as to what the user
meant. There is a big difference between a compiler trying to make as much sense as it can of invalid code and the language
having actual rules for the scenario, though. The scenario we're targeting specifically is files with one namespace in them
(and most often, one type as well), and these scenarios make up roughly 99.8% of C# syntax files that lived on one LDT-member's
computer. This includes the Roslyn codebase, which has several of these types of files specifically for the purposes of
testing that we handle the scenario correctly. Measuring an even broader set of millions of C# files on GitHub shows literally
99.99% of files have just one namespace in them.

We also briefly discussed the interaction with top-level statements. On the one hand, we're concerned about the readability of
combining these things, and that the namespace statement would be too easily missed. On the other hand, having just finished
talking about beginner scenarios, it seems like it might be annoying that beginners couldn't be introduced to the simple form
until they start splitting things apart into multiple classes. Users will likely police themselves here if it doesn't read well,
and maybe restricting it is just adding an arbitrary restriction.

#### Conclusion

We allow one and only one file-scoped namespace per file. You cannot combine a file-scoped namespace with a traditional
namespace directive in the same file. We did not reach a conclusion on the combination with top-level statements and will
pick that up again soon.
