Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Proposal: Simplifying Using directive statements #3668

Closed
ShreyasJejurkar opened this issue Jul 12, 2020 · 18 comments
Closed

Proposal: Simplifying Using directive statements #3668

ShreyasJejurkar opened this issue Jul 12, 2020 · 18 comments

Comments

@ShreyasJejurkar
Copy link

This proposal is to try to make using the directive statement better. using directive statement can get huge and bigger if we are importing stuff from a bunch of namespaces and most of the time it happens that it takes half of the screen if there are more using statements. And also we cannot use everything from a namespace directly like doing something like System.* which some languages support. Following is the cleaner way of doing this. This proposal is to introduce a new way of importing stuff while keeping the old one in place.

// current approch
using System.Collections.Generic;
using System.Text; 

As we can see above we are importing all stuff from parent System namespace and but still, we have to mention System every single time. I think we can make it better following this.

// new approach
using { Collections.Generic, Text } from System;

We can also have following this for more nested namespaces.

using { Generic, ObjectModel, Immutable } from System.Collections;

The advantages of the above approaches are that it saves space and at the same time, it expresses that things are getting used from parent System namespace (1st example ) without repeating System every single time.

But the next question arises that how can one use things from System namespace itself (like System.Console) along with above namespace. One of the approaches I am thinking about is to use this keyword here to reference System itself (This can be improved with a better approach for sure).

// here we are importing System itself along with Text and Collection.Generics
using { this ,Collections.Generic, Text } from System;

We can have static imports like below one with the new syntax. If we want to make all imports as static we can have following approach.

// both Console and Math are static in this case
using static { Console, Math } from System;

But in below case, only Math class is imported statically and not the Console class.

using { Console, static Math } from System;

For aliases, we can have the following way.

// here Mathematics is an alias for Math class. 
using { Console, Math as Mathematics } from System;

So these are just my thoughts about the new approach for using directive. Again, I need to make this clear is that this approach is the addition to what we currently have.
Moreover, I am always listening to community members for feedback on this. Thanks.

@theunrepentantgeek
Copy link

There have been a lot of prior suggestions for improving using declarations. For example ...

#3428
#3048
#2085
#1777

@ShreyasJejurkar
Copy link
Author

@theunrepentantgeek. Thanks for reply and those links and I wasn't aware of those links.
But those suggestions are not like same as mine. This is something different I have proposed and which is readable and uses less space at the same time.

@CyrusNajmabadi
Copy link
Member

using { Collections.Generic, Text } from System;

This would break basic intellisense scenarios. you would type using { and it would not be clear at all what to offer because System wouldn't have been typed yet.

@Joe4evr
Copy link
Contributor

Joe4evr commented Jul 12, 2020

This is something different I have proposed and which is readable and uses less space at the same time.

It doesn't matter that your proposal only looks different, they all boil down to the same thing: A desire to improve using directives. Bikeshedding over exact syntax should be done in only one thread to keep things centralized, so that if an LDT member would be interested in championing, they only have to look in one place to find all the community's suggestions.

@ShreyasJejurkar
Copy link
Author

ShreyasJejurkar commented Jul 12, 2020

using { Collections.Generic, Text } from System;

This would break basic IntelliSense scenarios. you would type using { and it would not be clear at all what to offer because System wouldn't have been typed yet.

I am not expecting IntelliSense should come as soon as I start typing using {.
This is just a way to improve readability.
And also we can have IntelliSense popup with suggestions once we complete from System statement.
We can have an analyzer that can parse from statement give suggestions into the IntelliSense for using statements.

// in between brackets we can expect IntelliSense to popup 
using {    } from System;

And also implementation in IntelliSense its another next thing.

@yaakov-h
Copy link
Member

In the 99% case, by the time I get to those brackets, there won't be any from syntax yet for Intellisense to use;

My IDE would show:

using {|

This is the same flaw that SQL-based intellisense suffers from globally, and why LINQ opens with "FROM" rather than "SELECT".

This is also very similar to #1696 whilst again just bikeshedding over the exact syntax and choosing one susceptible the intellisense flaw mentioned above.

@Unknown6656
Copy link
Contributor

Unknown6656 commented Jul 12, 2020

The IntelliSense issue could be solved with something like this:

using System.{ Collections.Generic, Text };
using static System.{ Console, Math };
using System.{ Linq, static Math };

(Which would also get rid of the from-keyword in using-statements ;) )

However, I am not sure that an "improvement" of using-statements is needed .... I think that they do not take away to much coding "real estate", and that an IDE could collapse the using-regions by default.

@ShreyasJejurkar
Copy link
Author

@Unknown6656 that .{ the syntax looks very wired to me, I don't know why but it does.

(Which would also get rid of the from-keyword in using-statements ;) )

That makes them more readable and natural.

I think that they do not take away to much coding "real estate", and that an IDE could collapse the using-regions by default

That is just an IDE feature and not a language feature.

@ShreyasJejurkar
Copy link
Author

@yaakov-h yeah, I got your point. But IntelliSense its kinda second step but we need to think first is this is a good feature to have.

@yaakov-h
Copy link
Member

yaakov-h commented Jul 12, 2020

@MCCshreyas we've had previous discussions on similar issues (some of which are linked above) around "is simplifying usings to collapse many usings from a single domain into one line" and so far it hasn't been widely agreed that this is beneficial to the language.

If it boils down to syntax I'd be in favour of something like using System { .Xml, .Linq } but maybe I've just been doing too much Swift coding lately.

Yet regardless of the shape that the syntax takes, the underlying principles and cost/value proposition (-100 points etc.) have to be in solidly in place.

If the problem of having too many usings can be solved by an IDE feature, and that feature can be widely implemented in popular IDEs (VS, VSCode, maybe Rider?) then it is much cheaper to go that route than to build a new language feature. Those can be implemented sooner and be more widely available, plus they can also apply to older syntax so nobody has to wait for C# 10.0 and .NET 6, or C# 11 and .NET 7, etc.

(I am completely making up the post-5 release schedule here, the exact details are not relevant.)

As for Intellisense, this is of extreme importance, and dictated the form of LINQ as I alluded to above. Compiler limitations and Intellisense limitations can easily kill a language proposal.

@HaloFour
Copy link
Contributor

Could borrow a page from Python and flip the clauses around:

from System using Collections.Generic, Text;

That would solve the autocomplete concerns. But, IMO, .NET namespaces aren't flat enough for that syntax to have that much benefit. Sure, you can knock out the duplication of System at the beginning of many of the BCL namespaces, but you'll still have nesting within those namespaces.

@qrli
Copy link

qrli commented Jul 12, 2020

I haven't been writing using directives manually in recent years. It had been Resharper doing that for me, and then Visual Studio itself.
For readability, I feel the existing dumb syntax is a lot easier to read and compare, especially when reviewing a git commit or pull request.

@MgSam
Copy link

MgSam commented Jul 12, 2020

If you spend more than .01% of your time writing or reading using statements then you're doing something wrong. Just about any C# IDE will be able to automatically add them for you as write code using various reference classes. The syntax you propose is demonstrably worse than what we have today for the reasons others have mentioned (the rare case that you have to write a using by hand and need intellisense). The minor savings on characters in a part of code that is essentially plumbing for the compiler is not worth any level of additional language design effort.

If you are concerned about screen real estate, VS will happily let you collapse the usings block...
image

@jnm2
Copy link
Contributor

jnm2 commented Jul 12, 2020

To @MgSam's point, I have long been interested by #3428 and I hope it lands soonish.

@svick
Copy link
Contributor

svick commented Jul 12, 2020

@HaloFour

IMO, .NET namespaces aren't flat enough for that syntax to have that much benefit.

The obvious solution to that is to allow nesting in the new syntax. E.g. instead of:

using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Text;

you could have something along the lines of:

using System { ., Collections { ., Generic, Immutable }, Text };

It's versatile and brief, but not very readable (when you see Text in the above code, you need to backtrack quite a lot to figure out what it actually means), so it's probably not a good idea.

@jnm2
Copy link
Contributor

jnm2 commented Jul 12, 2020

I almost never read or write the using directives directly. It's all adding via intellisense or code fixes while deep in the file, or removing via code fix from the error list. In that sense the list of using directives is doing a job similar to packages.lock.json for package restores. I never read that file either.

@orthoxerox
Copy link

If my list of usings is overly long, it's often a good indicator the type does too many things and it's time to refactor it.

@huoyaoyuan
Copy link
Member

This is just a way to improve readability.

I have to point out that, for people using other mother languages, putting the outer namespace at latter is decreasing readability.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests