csharplang/meetings/2021/LDM-2021-07-19.md
2021-07-26 17:46:50 -07:00

2.8 KiB

C# Language Design Meeting for July 19th, 2021

Agenda

  1. Global using scoping revisited

Quote of the Day

  • "Any guesses on how many tries it took for me to spell that correctly?" "Well, you misspelled it."

Discussion

Global using scoping revisited

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

The SDK team is currently considering how and where they will generate default global usings for .NET 6, and we want to take another look at our decisions around the scope of global usings. Previously, we decided that global usings should be thought of as being copied and pasted into every file, and that there is no separate outer scope for global usings. However, there are some type names that are relatively common in .NET, such as Task, that would likely be part of a default set of SDK global usings (as using System.Threading.Tasks.Task; is another way of saying "Use C# 5 features please"). If there is no separate global using scope for these types, however, we'd introduce ambiguities for these types.

There are a number of complexities to the separate scope idea that would be equally as painful for users, in potentially subtler ways. In particular, extension method lookup across multiple sets of usings can be tricky, and explaining the intricacies of the lookup rules is complicated, even for language designers talking to other language designers. This would hit Linq hard in particular, as System.Linq is on the shortlist of default global usings, but users often add their own versions of the extension methods to customize particular behaviors or performance characteristics for particular scenarios. In these scenarios, users would have to add a manual using System.Linq; at the top of their files, which is the same problem as we'd be trying to address by having separate scopes in the first place.

We considered a few compromise positions as well, such as considering global usings to be in the same scope for extension method lookup, but different scopes for type lookup. These are complex, both in terms of implementation and in terms of explaining to users, so we don't think this is a good approach. Instead, we think that we have a good tooling story around name clashes already, and we can strengthen the tooling to be aware of global using clashes and introduce global aliases to solve the issue, which is a fairly simple fix for the problem.

Finally, we noted that even if we introduced a separate scope for global usings, this wouldn't even fix the issue permanently. The next request would be a way to separate the implicit usings from the SDK, and the user-created global usings.

Conclusion

Existing behavior is upheld.