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: File scoped namespaces #2546

Closed
MgSam opened this issue Feb 17, 2015 · 45 comments
Closed

Proposal: File scoped namespaces #2546

MgSam opened this issue Feb 17, 2015 · 45 comments

Comments

@MgSam
Copy link

MgSam commented Feb 17, 2015

Background

.NET style guidelines recommend having at most one namespace per file. The current namespace syntax only allows block scope, resulting in every file typically having all of its contents (save using statements) wrapped in a namespace block. This leads to both vertical space being wasted (the curly braces used to delimit the block) and more importantly, horizontal space being wasted, with all of the important content indented by an extra tab (if style guidelines are being followed). The indentation from the namespace block conveys no useful information- it is just code bloat.

using System.Collections.Generic;

namespace Foo 
{
    public class Bar
    {
          ... // Potentially hundreds of lines of code, 
              // all of which has an extra indentation because 
              // of the namespace but is not actually conveying any useful information
    }
}

Proposal

Allow a single namespace declaration per file that has no braces and therefore no block scope. Every class written in the file is a member of this namespace. It would be an error to attempt to introduce a second namespace declaration of any kind (including one with block scope). The single namespace declaration would be valid in the outermost scope only. It would be valid to appear at any part of the file in this scope, although style guidelines would recommend putting it at the top.

namespace Foo;

using System.Collections.Generic;

public class Bar
{
    ...
}

Previous Discussion

Code Plex

Uservoice (vote for the feature)

http://visualstudio.uservoice.com/forums/121579-visual-studio/suggestions/7181921-file-scoped-namespaces

@alanfo
Copy link

alanfo commented Feb 17, 2015

I think this is an excellent idea which should be very easy to implement.

Just one point.

As using directives can be local to a namespace, there would be a difference in meaning between:

namespace Foo;

using System.Collections.Generic;

public class Bar
{
    ...
}

and

using System.Collections.Generic;

namespace Foo;

public class Bar
{
    ...
}

In the first case, the using statement would be local to Foo and, in the second case, it would be global .

However, there would be no practical difference between the two if no other namespaces were allowed in the file as specified in your proposal.

In the interests of simplicity, it might therefore be best to require that the namespace declaration should always be the first line in the file.

@MgSam
Copy link
Author

MgSam commented Feb 21, 2015

@alanfo The idea is that the namespace is file-scoped, so the question of whether a using statement is local to a namespace or not doesn't really apply. In your examples the behavior would be exactly the same.

However, I do think that the rules for such a file-scoped namespace should probably mirror the rules for using statements. Thus, maybe it makes sense to require that the namespace is always the first non-comment, non-preprocessor line in the file.

@AdamSpeight2008
Copy link

What about the case of a partial class spread across multiple files, having different file-scoped namespaces

@RichiCoder1
Copy link

Wouldn't it ultimately end up meaning the same thing? File scoped just means the entire file lives in that namespace rather than allowing multiple.

@alanfo
Copy link

alanfo commented Feb 21, 2015

@MgSam
Yes, I agree that it makes sense to require that the namespace is always the first non-comment, non-preprocessor line in the file.

@AdamSpeight2008
The compiler would only combine partial classes with the same name if they were in the same namespace, whether file-scoped or not. They would be different classes otherwise.

@RichiCoder1
Yes, it would be the same thing as putting the entire file within a single namespace. However, if the proposal were adopted, it would save you having to indent the file contents by an additional level. As a file having a single namespace is probably the commonest case, this would be a worthwhile improvement in my view.

@qrli
Copy link

qrli commented Feb 22, 2015

This is what I hoped from version 1. it is not only wasting space, it also makes extra level of brace, where you'll need some IDE plugins make it easy to tell what each brace is for.
It was a copy of C++'s namespace but we know how combersome it is from the managed C++ experience.

@RichiCoder1
Copy link

Haha, sorry @alanfo, that was a response to @AdamSpeight2008. I absolutely agree.

@zgxnet
Copy link

zgxnet commented Mar 6, 2015

Absolutely support! This is a very nice feature. It is really a waste of indentation to put every class inside a namespace scope. And it is an easy feature.

@mkosieradzki
Copy link

The indentation point is actually quite convincing. This is going to be a long shot: all this makes sense because statistically many developers actually have single namespace per file, but many developers also have single class per file and some nested classes. Maybe it's a good idea to allow similar syntax for classes then?

public sealed class Foo.Bar;

using System.Collections.Generic;

public sealed class MyNestedClass
{
    ...
}

public string Method1(int arg1)
{
     .....
}

or

namespace Foo;
public sealed class Bar;

using System.Collections.Generic;

public sealed class MyNestedClass
{
    ...
}

public string Method1(int arg1)
{
     .....
}

@zgxnet
Copy link

zgxnet commented Mar 6, 2015

Very nice proposal. I like the idea of file scope class. It will allow very clean code.

@tenor
Copy link

tenor commented Mar 6, 2015

I don't see any real benefit to this proposal. It saves the developer a few keystrokes per file and removes an extra level of indentation (which any decent IDE can do automatically) but doesn't improve readability.

@paulomorgado
Copy link

Having something scoped to the compilation unit (file) is nothing new to C#. using directives can be scoped at the compilation unit level or namespace body level.

Because there are differences between compilation unit scoped and namespace scoped using directives, the proposal should account for that.

The using keyword is used for the using directive and the using statement but de difference is clear, not only because of where they are used, but how they are used. The using directive is a directive (there aren't many of them in C#) and has no body and the using statement has a body.

If fact, all statements introduced in C# (or not present is languanges commonly used at the time) that have associated statements/bodyes (lock, using, get, set) require them to be a block statement (with curly braces). I think they should have gone further and foreced that also for the others (if, while).

This proposal doesn't seem to fit well with C#.

If you really feel that those characters lost on the left are that important, I propose that the namespace declaration might be used without the curly braces, meaning that it will apply to whatever is next:

namespace N1
    namespace N2
        class C1 {}

namespace N1
    namespace N2
        class C2 {}

Or, beacause that space matters:

namespace N1
namespace N2
class C1 {}

namespace N1
namespace N2
class C2 {}

But, then, it becomes just about formatting (tooling):

namespace N1
{
namespace N2
{
class C1 {}
}
}

namespace N1
{
namespace N2
{
class C2 {}
}
}

Does that really worth all the hassle of the change?

How about this, instead?

class N1.N2.C1 {}

class N1.N2.C2 {}

@mkosieradzki
Copy link

I think @paulomorgado proposal is a nice compromise. It can be done, because namespaces do not have any modifiers what makes them different from classes, methods and so on.

@MgSam
Copy link
Author

MgSam commented Mar 6, 2015

Because there are differences between compilation unit scoped and namespace scoped using directives, the proposal should account for that.

I think this is an implementation detail. Is there a difference in behavior to the user? If not than it doesn't really matter which is used.

If you really feel that those characters lost on the left are that important, I propose that the namespace declaration might be used without the curly braces, meaning that it will apply to whatever is next:

This would be both confusing and demonstrably less useful. Style guidelines recommend one class per file, but often you see files with more in them than just a single class. More than one namespace per class, on the other hand, is almost never seen.

I don't see any real benefit to this proposal. It saves the developer a few keystrokes per file and removes an extra level of indentation (which any decent IDE can do automatically) but doesn't improve readability.

Visual Studio has certain defaults for files and auto-formatting behaviors it uses; C# has style guidelines which the vast majority of devs generally follow. All of these include a namespace enveloping the entirety of the file and indentation associated with that namespace. It's nice to talk about a hypothetical world in which this isn't a problem but the fact is the overwhelming majority of code will continue to use the current style unless there's a compelling language-based reason not to.

@mkosieradzki
Copy link

For imperative-style it is a minor upgrade, but for functional-style it's a major upgrade. In imperative style you have a lot of short instructions one per line, control structures makes a lot of indents and outdents. In functional approach you have some definitions - sometimes one-per-line each consisting of usually long expression where IDE gives hand with utilities like word-wrap.

I think this couple of characters saved on the left will cause further word-wrapped lines to start earlier accumulating saved space on per-line basis. Consequently it means more actual lines visible per page and consequently more options to logically arrange code. It's far more than code will be more on the left.

@MgSam
Copy link
Author

MgSam commented Mar 7, 2015

I added a link in the proposal to UserVoice, so you can vote for the feature if it interests you.

@paulomorgado
Copy link

@MgSam,

Because there are differences between compilation unit scoped and namespace scoped using directives, the proposal should account for that.

I think this is an implementation detail. Is there a difference in behavior to the user? If not than it doesn't really matter which is used.

§9.4.2 (Using namespace directives) does not mention the differences, but §7.6.5.2 (Extension method invocations) states that:

Starting with the closest enclosing namespace declaration, continuing with each enclosing namespace declaration, and ending with the containing compilation unit, successive attempts are made to find a candidate set of extension methods:

This is valid for everyting namespace related. Using directives inside a namespace declaration superside any outer using directives.

So, this is not a style issue and, definetely, there's a difference to the user.

@tenor
Copy link

tenor commented Mar 9, 2015

Hmm, nested namespaces brings up some interesting issues:

    namespace Namespace1;
    namespace Namespace2 {
        class C {}
    }

Does class C belong to Namespace1.Namespace2 namespace or Namespace2 namespace?
Should the compiler disallow other namespace declarations if a file scoped namespace is in use?

@MgSam
Copy link
Author

MgSam commented Mar 9, 2015

@paulomorgado @tenor I think the same part of the spec I proposed answers both concerns:

It would be an error to attempt to introduce a second namespace declaration of any kind (including one with block scope).

So binding extension methods is not an issue since all using statements would be within the same namespace scope.

It would be unnecessarily confusing and complicating to allow namespace blocks to be declared when a file-scoped namespace is present.

@jnm2
Copy link
Contributor

jnm2 commented Mar 18, 2015

I like this idea. The forced amount of indentation has been a minor annoyance over the years. I'm not sure I'd be comfortable doing the same thing to the class declaration, but the beauty of this proposal is that it would work either way according to your preferences.

I have a possible alternative to the single line namespace. What about allowing namespaces in class names? It achieves the same goals more concisely:

using System;

public class MyNamespace.ClassName
{
    [...]
}

@paulomorgado
Copy link

That was my proposal, @jnm2.

And it's not as strange as one might think because this:

namespace N1
{
    namespace N2
    {
        class C
        {
        }
    }
}

is already the same as this:

namespace N1.N2
{
    class C
    {
    }
}

@jnm2
Copy link
Contributor

jnm2 commented Mar 18, 2015

Oh, my bad. I'm 100% with you there.

@pawchen
Copy link

pawchen commented Oct 13, 2015

Nice, I like this. Just one max per compilation unit would be enough I think.

Some say, saving spaces improve compilation speed. I don't know, but it does improve readability, good for portrait screen coders, too.

@paulomorgado
Copy link

Ouch!

@jnm2
Copy link
Contributor

jnm2 commented Mar 26, 2016

It would be fantastic if I could specify both namespace and partial class:

public partial class MyNamespace.MyClass
{
    [...]
}
private class MyNamespace.MyClass.UtilityClass
{
    [...]
}

@anirudi
Copy link

anirudi commented Apr 21, 2016

Perfectly agree. It does not make sense to intend on namespace as anyways we can have only 1 namespace in a file.

@AdamSpeight2008
Copy link

We can as it is allowed by the C# grammar. Just because a majority of examples use only one, doesn't indicate that only one is allowed.

@int19h
Copy link

int19h commented Sep 10, 2016

It's not just the majority of examples. It's a well-established code style guidelines, used by .NET Framework itself among other things.

If the de-facto official style guide results in unnecessarily verbosity (in this case, wasted indentation) for 99% of lines in every source file, something is clearly wrong.

One possibility is that IDE should simply never indent the body of the outermost namespace declaration. This is common in C++, but also fairly ugly.

Otherwise, I think the most reasonable approach is to come up with some simple syntactic sugar - in other words, whatever the syntax is, it should have a straightforward desugaring into the existing namespace { ... } declaration, and then all existing rules (for nested usings etc) should apply exactly as they do today.

Since there are already a few suggestions above, I'm going to add one more:

namespace Foo:
class Bar { ... }
enum Baz { ... }
...
namespace Nested {
   ...
}

So basically the same as the proposal, but using : to signify that everything that follows is the namespace body. This is consistent with case ...: in C#, and also with access specifiers in C++, so hopefully this syntax would reduce confusion.

There are only two simple rules for desugaring this:

  1. namespace X: ... becomes namespace X { ... }, where ... is everything after : up to the end of input.
  2. namespace X: form is only permitted in global namespace - this prevents nesting. If you need to nest namespaces, use {} for inner ones. It also means that there can be at most one namespace: per file, although it can follow after several namespace{} blocks.

This takes care of the 90% case (single namespace in a file) with straightforward, easy to understand syntax, and avoids adding new rules or creating corner cases.

@dsaf
Copy link

dsaf commented Sep 15, 2016

Frankly speaking, this feature would have more positive impact on an average codebase than e.g. pattern matching. It's one file per type most of the time, and we remove 2-3 lines of code and a whole indentation level. I only like @jnm2's/@paulomorgado's syntax though.

@anirudi
Copy link

anirudi commented Sep 15, 2016

BMSEphx

Get Outlook for Androidhttps://aka.ms/ghei36

From: dsaf
Sent: Thursday, September 15, 3:49 PM
Subject: Re: [dotnet/roslyn] Proposal: File scoped namexxx

Frankly speaking, this feature would have more positive impact on an average codebase than e.g. pattern matching. It's one file per type most of the time, and we r emove 2-3 lines of code and a whole indentation level.

You are receiving this because you commented.
Reply to this email directly, view it on GitHubhttps://github.com/dotnet/roslyn/issues/595#issuecomment-247290710, or mute the threadhttps://github.com/notifications/unsubscribe-auth/AQ8OVOxvoE9bwOzV3mwD5cQOjtSxKbNZks5qqRuUgaJpZM4Dhtaj.

@whoisj
Copy link

whoisj commented Sep 29, 2016

Frankly I'd even take the ability to do class names long hand even.

public class Namespace.ClassName
{
    // define class here...
}

What ever it take to get the extra white-space out of the left side. Some of us are trying to live within character limited columns (not my idea).

@alrz
Copy link
Member

alrz commented Feb 16, 2017

@MgSam I really like this feature, perhaps you want to port this to csharplang repo?

@MgSam
Copy link
Author

MgSam commented Feb 16, 2017

@alrz Did they state they're not going to port the issues over and its up to the community?

@alrz
Copy link
Member

alrz commented Feb 16, 2017

its up to the community?

@MgSam From what has happened so far, unless it's already championed, yes.

@jnm2
Copy link
Contributor

jnm2 commented Feb 16, 2017

@MgSam yes please port.

@AustinBryan
Copy link

Shouldn't style conventions prefer

using System;

namespace MyNamspace;

public class MyClass { ... }

Over

namespace MyNamspace;

using System;

public class MyClass { ... }

As it looks closer to what we're used to:

using System;

namespace MyNamespace
{
    public class MyClass { ... }
}

And we're already in the habit of checking the line right above the class name to find the namespace.

@paulomorgado
Copy link

What style conventions?

@gafter gafter transferred this issue from dotnet/roslyn May 19, 2019
@aka-nse
Copy link

aka-nse commented May 24, 2019

I like fully qualified naming style such as suggested by @jnm2 and @paulomorgado. This is consistent with type-using grammar, and also with type declaration grammar in MSIL.

@ssg
Copy link

ssg commented Jan 5, 2020

I wrote my thoughts about file-scoped namespace directives here: https://medium.com/@ssg/a-pledge-for-namespace-directives-in-c-15a322504a15

@janniksam
Copy link

Although this proposal is over 5 years old now, I personally do love this idea aswell.
Since C# 8.0 introduced using declarations, in my opinion this is the next big step to work on.

Personally I never saw (well, remember) a file, that contained more than one namespace. This would save some indentation in all my files, so I can abuse it for one more nested if to annoy my co-workers in the next pull-request with... ;)

@mkArtak
Copy link

mkArtak commented Mar 29, 2020

What about supporting implicit namespaces?
In majority of projects I've worked for, the namespace is always a combination of projectName + folder structure to current file. If this can be treated as default, there won't even be a need to specify namespaces explicitly.

Of course, for completeness, this will require:

  • to have an ability to define a root project-level namespace (which I think is already supported through the RootNamespace property in the project file).
  • a mechanism to override, which is what this issue about

@ssg
Copy link

ssg commented Mar 31, 2020

@mkArtak An upgrade to that model would entail reorganizing your project folder structure (or your code) significantly which is very intrusive in my opinion. File-scoped directives, on the other hand, can even work with a simple refactor (even find & replace perhaps), and would not even change the diff significantly if you omit whitespace.

Also, C# namespace directives are case-sensitive while MacOS/Windows file systems are not. My Spider-sense says trouble.

@mkArtak
Copy link

mkArtak commented Mar 31, 2020

@ssg, for an existing project scenario you're referring to, you will still be able to specify explicitly the namespace per file. My proposal goes a step beyond that by eliminating the need for specifying the namespace if the name matches the convention [default namespace].[folder structure]
As for for the OS case sensitivity, these I think are minor technical challenges, which can be solved using a few more project-level properties.

@umbarov
Copy link

umbarov commented Jul 10, 2020

I like this idea. Pros are less indents and compactness . Other programming languages like Java, Go, Rust, Python do not use namespace braces. I spend a lot of time on review and I get annoyed by the indents and horizontal scrolling. Another advantage is that the code is left-aligned.

@333fred
Copy link
Member

333fred commented Jul 13, 2020

Closing as a duplicate of #137.

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