Hacker News new | ask | show | jobs
by t-writescode 1689 days ago
Oh wow. I do not like that "global using". It harkens to the auto-loading issues I've had with Rails. "Where was this defined? I dunno! It probably works here, though!!1"

I generally don't like a random file impacting several other files. Extension methods are ... tolerated and ... "fine" but I still feel unpleasant using them.

File-Scoped namespaces seem like someone's really, really tired of having nested folders and seems actively unnecessary.

I like natural lambda types

Good update on parameterless structs. I assumed that's how they worked already. I haven't used C# in 2 years; but you could do that with classes back when, so I assumed it would be the same with structs.

Constant interpolated strings is nice.

Extended property patterns is fine, just probably not for me.

5 comments

> Oh wow. I do not like that "global using". It harkens to the auto-loading issues I've had with Rails. "Where was this defined? I dunno! It probably works here, though!!1"

It's been a feature of Visual Basic .NET for a very long time (from recall: at least 2008), I'd hope Microsoft heavily queried user feedback before implementing.

https://docs.microsoft.com/en-us/visualstudio/ide/how-to-add...

File-scoped namespaces is nice to not have every class already sitting at one level of indentation. I don't see what it has to do with nested folders.
To be fair, global usings aren't fundamentally different from assembly references (which have always been per-compilation rather than per-file).

With respect to parameterless struct constructors: the reason why C# didn't have that historically is because there are many corner cases where those aren't invoked in CLR. Basically any place where you can't do "new" directly on the struct itself - e.g. when you create an array of structs, its elements do not have the constructor run for them. So C# designers originally decided that it would be less confusing overall if structs were always default-init, in all contexts - which means no parameterless constructors. I'm not sure what prompted the change of mind.

I do not like that "global using" as well. I wonder why they added it.
Looks like they added global usings to support their implicit usings functionality. Essentially they want to save people having to put using System, System.Linq, System.Collections.Generic, and others[0] at the top of nearly every C# file.

I'm of two minds:

- I think they're an anti-pattern, because it creates a global scope that can get messy/annoying.

- It makes a ton of sense for the implicit usings functionality, and I'm tired of needing to add the basic SDK usings to every source file.

So the ideal is to enable .Net's implicit usings, then to use an analyzer to "ban" adding more global usings directly from your solution/project. Best of both worlds that way. Alternatively just make them a no-pass item for code reviews.

[0] https://docs.microsoft.com/en-us/dotnet/core/compatibility/s...

It's literally the same as Rust's prelude system and I don't see anyone complaining so much about this.
Rust doesn't have anywhere near the following of C#, so there probably aren't enough opinionated people in the community to mention it on an HN post
> Essentially they want to save people having to put using System, System.Linq, System.Collections.Generic, and others[0] at the top of nearly every C# file.

Interesting that this doesn't bother me at starting from .net 1.0. All tools (including raw VS without addins) can add those using automatically and they do.

But for me it's still a nice to have feature if VS will be able to show where this using is defined.

This is what I’ve settled on. Implicit usings for the SDK are great but otherwise I don’t want this in any code base I work on.
Because most files in C# start with:

using System; using System.Collections.Generic;

and a few more lines like that. Think of this part of the BCL as the prelude in Haskell.

It's an easy way to do a config without a full importer and complexity in passing config around / looking it up.

I like it. This goes way back. They give the example of a globalusings file.

That's a cheap / easy way to do a config file (at least one use case).

Doesn't really bother me, so long as the global usings are only kept to a single file. Intellisense will tell you the full namespace, then you can just see if you've got that namespace in the file you're in or in your dedicated global usings file.
> so long as the global usings are only kept to a single file

Here's where the mess starts.

It seems far too easy to sneak a global import statement in to random files and then have the entire codebase polluted by it.

I feel like this is too foot-gun'y, myself.

Yeah, there should definitely be a way to have the compiler enforce global usings in only a specific file.
I thought it was generally considered good practice to put extension methods into static classes in their own file. So like `FooExtensions.cs` if you are writing extensions for the `Foo` class.

I would consider this the same: Project should have a `GlobalUsings.cs` file.

Does C# have any linters available that could enforce such a conventions?

C# has a framework in-place to facilitate workspace-specific linters, so even if one doesn't exist, it could be written very easily (and premade ones are sure to appear quickly).

https://docs.microsoft.com/en-us/dotnet/csharp/roslyn-sdk/tu...