csharplang/meetings/2021/LDM-2021-01-13.md
Fredric Silberberg f80973d27c
Reverse a word
2021-01-14 16:46:40 -08:00

6.2 KiB

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

Agenda

  1. Global usings
  2. 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, 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.