Open bomzj opened 7 years ago
Assembly attributes [assembly: Foo]
would be disallowed in the presence of a namespace directive?
I never understood why namespace directives were relevant to the placement of assembly:
attributes.
currently you can't have assembly attributes after any namespace declaration. usings come first, then assembly attributes, and finally namespace decls. with the requirement of namespace directives being the very first part of the compilation unit (like Java's package
), following the existing rules, you can't use assembly attributes and namespace decls at the same time.
I know, and I honestly don't understand why not. You're clearly targeting the assembly either way.
Wouldn't one ideally list all their assembly-wide attributes in a dedicated file? (Usually AssemblyInfo.cs
, which although missing from .NET Core-style project templates, is easy enough to add manually.)
@Joe4evr
Wouldn't one ideally list all their assembly-wide attributes in a dedicated file?
That would be a convention vs. what's "possible" in the language.
@Joe4evr I've been known to put things like [assembly: DefaultCharSet]
other places.
In Java I hate package for their naming convention. In C# I hate namespace for excessive hierarchy. Change package naming conventions is too late. But add new syntax is always possible, so I hope for you guys. Sorry for offtop. I just always wanted this syntax.
@jnm2
Can we just remove need of curly brackets? It shouldn't change compiler logic much:
using System;
namespace My.Namespace public class ClassName
{
}
@mharasimowicz Hmm. For some reason I'm not liking that.
It shouldn't change compiler logic much:
It changes every piece of code that currently assumes the containing namespace can be found by just walking upwards to find a parenting namespace declaration node.
But add new syntax is always possible
It's always possible, but in a similar fashion, if it's not valuable enough it's not worthwhile to change things and introduce dialects. C# is 17 years old now. Changing things is fine, if it has substantial enough benefits. Here, i just don't see it.
--
Or, put another way: often times there are things we'd like to do with syntax. However, we try to tie them to some substantially new thing that doesn't already exist today.
Another way to think about it is this: top level syntax is not where people spend the majority of their time. It's inside a method body where most of the action happens, and where you can get most of the bang for your buck around syntax changes.
@mharasimowicz Hmm. For some reason I'm not liking that.
Agreed. That looks terrible to me.
Another way to think about it is this: top level syntax is not where people spend the majority of their time. It's inside a method body where most of the action happens, and where you can get most of the bang for your buck around syntax changes.
@CyrusNajmabadi Every method body you're ever written in C# has an unnecessary extra level of indentation because of the namespace. Even when the standard practice since C# 1.0 has been one namespace per file.
Sure, maybe that extra layer of whitespace doesn't matter when you're at a desktop with a 30 inch monitor, but when you're writing code on a small laptop screen, for example, every character on the line matters.
maybe that extra layer of whitespace doesn't matter when you're at a desktop with a 30 inch monitor, but when you're writing code on a small laptop screen, for example, every character on the line matters.
Not to mention, GitHub PRs have a fixed width. Less indentation means less need for wrapping so you'd have cleaner code at the end.
but when you're writing code on a small laptop screen, for example, every character on the line matters.
Ask anyone on the roslyn team. I do 100% of my development on a 14" laptop :) Literally every line of Roslyn code i've ever written has been in a window this size:
Seriously, the entire team will back me up that this is how i code. I actually prefer this because it lets me focus on what matters, without distraction.
Every method body you're ever written in C# has an unnecessary extra level of indentation because of the namespace
The important bit for me is this: i never write that. It's not like i'm typing spacespacespacespace. I'm typing my actual code, and things like indentation are being handled for my by my environment. It's not something I need to be involved with.
Even when the standard practice since C# 1.0 has been one namespace per file.
Yes. And that's a very good point. It's been the standard practice since c# 1.0. It's not like people were writing code like this all that time:
namespace A.B.C
{
class D
{
}
}
People have been writing C# it with the indentation all this time. I don't see why we'e now 17 years into things want to introduce a new dialect and spend all that engineering effort to something that doesn't seem to actually substantively improve the expressiveness of the language, while actually introducing a different dialect.
Again, if this were C# 1.0/2.0, i'd likely feel different. But, frankly, i'd rather hte effort be spent on things that directly lead to significantly improved programs. i.e. things that affect the actual code that is written, not the presentation of that code.
If you really want to not have indentation here, don't add a language feature, instead add a formatting option. IT will be literally 1/100th the cost, and would easily be accepted over trying to actually change the language.
@CyrusNajmabadi
Well, one way we might be able to solve this is through (future, aka 100 years 😆) source generation.
With something like this:
[Namespace("A.B.C")]
class D
{
}
Just an idea.
What about rule if class is not in namespace, then just use current project path
? For example:
/MyApp/My/Cool/Path/Program.cs
using System;
class Program
{
static void Main(string[] args)
{
}
}
become:
using System;
namespace MyApp.My.Cool.Path
{
class Program
{
static void Main(string[] args)
{
}
}
}
If people don't like default naming convention physical path is actual namespace path, then they could just write it explicitely:
using System;
namespace MyApp.I.Dont.Like.Your.Convention
{
class Program
{
static void Main(string[] args)
{
}
}
}
@Pzixel It's breaking. top-level types belong to the global namespace.
@alrz but we may change context via something like
namespace default;
using System;
public class Product
{
...
}
it's an extension of original proposal, where we don't specify namespace manually.
Otherwise we have no option but write rules that namespace declaration adds no intendation. It seems easier but harder to read than one declaration on the first line.
@Pzixel What is a "current project path"? Consider:
Foo
, files in the Foo.Bar
namespace might be under the path of src/Bar
. Though there isn't a single standard way to structure a C# project (precisely because it didn't matter to the compiler)..csproj
root.@Pzixel
C# compiler does have a notion of project, see Roslyn API.
You can't specify a project when compiling with csc
or when you use Microsoft.CodeAnalysis.CSharp.CSharpCompilation
. Sure, there is Microsoft.CodeAnalysis.Project
, but that's part of the Roslyn Workspaces API, which is not really part of the compiler itself.
Relative to .csproj root.
Then what happens when the relative path is something like ..\..\Common\src\Microsoft\Internal\EmptyArray.cs
?
@Pzixel
But honestly, your proposal doesn't make "file-scoped namespaces" as described in this thread, any easier or better, if it doesn't make it harder to implement. Note that the concerns mentioned in https://github.com/dotnet/csharplang/issues/137#issuecomment-345550024 still applies to namespace default
in one way or another.
@svick
Then what happens when the relative path is something like ....\Common\src\Microsoft\Internal\EmptyArray.cs?
Nah, you beat me :)
@alrz I agree, but if it worth we can extend this logic that namespace may be just specified once in the beginning of the file. I also agree, that probably the best we can do is no-op or custom code style. However, probably there is some alternative way we don't see yet.
@Pzixel,
Like others, I don't feel that namespace default
adds anything but extra complication to the original proposal:
namespace Company.Project
using System;
public class Product
{
...
}
which is simple and elegant.
And in my view, @CyrusNajmabadi's concern re "It changes every piece of code that currently assumes the containing namespace can be found by just walking upwards to find a parenting namespace declaration node." is non sequitur. Firstly, the namespace node could still exist in the same place in the syntax tree, and secondly, since namespaces can be nested, walking up that tree to that first encountered namespace node is not currently a reliable way of getting the namespace.
And even worse is his hack solution of just not indenting the type blocks inside that namespace. An ugly botch is not a good alternative to the elegance of this proposal I do not think that the idea of not indenting within the namespace block is a nice solution. It runs counter to the near-universal convention of how C# code is laid out. I think it very inelegant compared with this proposal.
(Edited as my original comment was far too much an attack on Cyrus, rather than explaining why I didn't like it).
And even worse is his hack solution
ugly botch
If I didn't know better I'd think you had a chip on your shoulder for someone... 😁
Hmm, when you selectively quote my comment, it does seem somewhat negative 😆
I was going to quote the whole thing at first, but I felt like that was a fair summary. 😆 Can easily fix...
Oh, no, it's OK. It's not unfair selective quoting. Your point is well made. I need to be more careful with my enthusiasm to be, well rude (especially to @CyrusNajmabadi, who seems all too often to be the target of that rudeness).
I have updated it to hopefully be less aggressive.
is non sequitur.
It's really not. Trust me, i've written a bunch of code that works that way :)
I do not think that the idea of not indenting within the namespace block is a nice solution. It runs counter to the near-universal convention of how C# code is laid out.
Right. People indent namespaces today. This whole proposal is a way to make it so people don't have to do that. IN that regard, this proposal itself is counter to the near-universal convention of how C# is laid out. Given that some people want this, i don't know why we need it from a new language feature (cost: roughly 1 million cybucks) vs just submitting a PR for a formatting feeature (cost: roughly 1k cybucks). Seriously, if you don't want indented classes, and you feel like you're wasting horizontal space across the entire project, and you're ok with your code not looking like the near-universal patterns of the rest of C# out there: Then just make a formatting option. :)
FWIW, i didn't take it as an attack. And, to address hte main point:
An ugly botch is not a good alternative to the elegance of this proposal
Yes, it really is. Why? Because forcing a ton of time and effort to get almost the same result that you can effectively get today is a bad decision. Think about all the times you go "man... i wish the team could hurry up and get around to active patterns". Now think about what a feature like this is. To do it, it would occupy someone's time great. They have to get the proposal all the way through the LDM. Then they have to change the syntax model of the compiler to support it. Then they have to touch everything in the compiler that deals with namespaces to make sure it works. That means writing a test for every possible language feature that can be affected by namespaces.
Then, once that is done, every IDE feature needs to be tested in the context of this this new namespace construct to make sure they do the right thing. And features like formatting/rename/etc have to be updated to do the right thing for them.
That's literally man-weeks of effort. To get you to the point where all you've gained is that you don't have indent your nested constructs, and you can avoid an extra { }
by replacing it with a ;
.
Yes, this proposal is the most 'elegant'. Great. That elegance cost weeks of time that could be spent providing a lot more bang for the buck for the user. That's bad engineering IMO, and not the right decision for the team right now.
--
Note: if this were to be done, i would much rather have be as part of some sort of cohesive and invested effort in some sort of C#-light dialect. Similar to #light
in F#. In other words, really attack the overall verbosity/nesting issue with a set of cohesive feature that overall worked together. Then there could be economies of scale going on. Instead of someone having to pass over the entire IDE codebase just to test out one thing, they could instead collect a bunch of syntactic improvements together and only spend a few percent more time to get a lot more features in the hands of users. That's something i can at least get behind given the size of the improvement that would come along with the cost of the work.
if this were to be done, i would much rather have be as part of some sort of cohesive and invested effort in some sort of C#-light dialect
I thought the LDM was vehemently against making different dialects of the language.
I thought the LDM was vehemently against making different dialects of the language.
I think they are :) But since we're discussing dialects with this proposal anyways... :)
Another way to solve this is add a different representation of the source code to the IDE where certain things are removed, something like "compact/lightweight view" that doesn't show namespaces and maybe other things.
I understand that when browsing the source code through different tools other than VS it would still be a distraction but at least when you're working on the code you could have the option not to show it.
There's been a lot of different proposals on this thread, but I'm giving a +1 to @HaloFour's suggestion that we treat this like the Java package
directive: one per file, must be first directive in the file, i.e.:
namespace My.Company;
using System;
public class MyClass {
...
}
And of course allow the old container syntax so that this is not a breaking change.
Benefits: less indentation, less horizontal scrolling, better enforcement of one-namespace-per-file per StyleCop rule SA1403. I would exclusively use this feature if it were available to me. I cannot recall a single time that I've needed multiple namespaces in a file, so this would be a very welcome change.
FWIW, I would also use the public class My.Company.MyClass
alternative if that's the decision. I like the namespace directive better so that you don't have to repeat it if you have multiple classes in a file, which I feel is much more common than multiple namespaces.
There's been a lot of different proposals on this thread, but I'm giving a +1 to @HaloFour's suggestion that we treat this like the Java package directive: one per file, must be first directive in the file, i.e.:
namespace My.Company;
using System;
public class MyClass {
...
}
So you can't do:
using System;
namespace My.Company;
public class MyClass {
...
}
?
That means a lot of code won't be able to easily transfer over. As moving the using from outside the namespace to inside can change its meaning, causing code to break.
Benefits: less indentation, less horizontal scrolling, better enforcement of one-namespace-per-file per StyleCop rule SA1403.
None of these need a language change. Less indentation can be fixed at 1/1000th the cost by just chanding the formatting.
Less horizontal scrolling would call out of the formatting change.
Seriously. To put it in perspective. This feature could have been done in an hour or so the day this was proposed back in the formatting engine. It could have been available months and months ago. Waiting to get it as a language feature means waiting years (or possibly forever) to get it.
If this is important to you, i would recommend just fixing the formatting engine, submitting a PR, and getting the problem solved today instead of hoping this will go anywhere in the next decade :-/
@CyrusNajmabadi This has been said already, but "fixing" the formatting engine doesn't fix the problem. 99.99% of the code out there will continue to use the Microsoft-recommended style of an extra layer of indentation. And lots of people wouldn't like having a bracketed scope without a corresponding layer of indentation. Your argument is equivalent to "why do we need expression-bodied methods, properties, etc when you could just put the brackets, et al on the same line?"
Why should this have to wait years to happen? You guys are doing point releases now, this could easily be discussed, approved, and implemented in just a couple of LDMs if someone would champion it and then it could be shipped in a point release.
As far as I can see, the real bottleneck is getting someone to champion it. And passing that bar for any community-suggested feature is extremely difficult. Yet silly features like a dictionary literal syntax (that would on rare occasions save you at best a few characters and make no meaningful readability difference) get discussed in LDM solely because Miguel suggested it.
@CyrusNajmabadi There are few guidelines which are more consistently applied than indenting inside curly braces. This is true throughout the C# ecosystem and even across nearly all curly-brace languages (despite disagreements on whether to place the opening brace on a separate line).
Suggesting we change such a fundamental idea can't be taken very seriously.
@bondsbw I believe @CyrusNajmabadi is saying that it's easier to change these guidelines, than the language. Nothing is preventing you from following this new guideline No spaces after namespace declaration
, it's a question about habits.
I originally proposed something that could be worthwhile, however, I've got convinced that it isn't.
If you think that change the language is easier than change people habits - it isn't.
@Pzixel This proposal obviously needs to beat others bang-for-buck in order to prioritize it for implementation. I don't think anyone has said otherwise.
@CyrusNajmabadi
If this is important to you, i would recommend just fixing the formatting engine, submitting a PR, and getting the problem solved today instead of hoping this will go anywhere in the next decade :-/
Could you link the repository, please? I think it's not Roslyn because it's representation question, while VS sources are not OSS. On the other hand, Roslyn generated code has some indentation rules, so probably it still may be possible to PR in Roslyn repo for this feature.
Suggesting we change such a fundamental idea can't be taken very seriously.
It's far easier to get people to adopt a new coding style than it is to introduce an entire new language feature and then get people to move to that language feature over the existing one.
Could you link the repository, please? I think it's not Roslyn because it's representation question, while VS sources are not OSS.
This could be done 100% in github.com/dotnet/roslyn. The formatting engine, the editor-config support and the options for VS are all in that repo.
This proposal obviously needs to beat others bang-for-buck in order to prioritize it for implementation.
I think the problem then is that "changing the formatting engine" kills this, at least in terms of "bang for buck".
Changing the formatting engine:
Changing the language:
So, right off the bat, just changing the formatting engine is super nice.
But formatting doesn't just get rid of the indentation. It also breaks one of the most fundamental conventions in curly-brace language programming.
Your "buck" is one that was found in raw sewage. It is technically worth a dollar, but nobody wants it.
It also breaks one of the most fundamental conventions in curly-brace language programming.
This whole 'feature' is about changing the conventions around C#. So i don't see what the problem is.
We also have already allowed indentation flexibility with curly braces today with 'switch' and the indentation (or not) of the case sections.
--
Finally, i would point out that when it comes to 'curly brace' languages, all you can say about conventions is that there are no 'fundamental' conventions.
For example (from https://en.wikipedia.org/wiki/Indentation_style)
K&R:
while (x == y) {
something();
somethingelse();
}
Allman
while (x == y)
{
something();
somethingelse();
}
Gnu
while (x == y)
{
something();
somethingelse();
}
Whitesmith
while (x == y)
{
something();
somethingelse();
}
Etc. etc.
The only 'fundamental convention' that i've been able to glean about the curly-brace languages is that people do what they want, and you follow the patterns of the codebase you're in.
I see no reason why it would suddenly be a crazy idea that you update the formatting engine to not indent some curly-brace contents especially given C# has already shipped with such an option for many years already.
@CyrusNajmabadi Those examples prove my point. All of them use the same indentation for block content (even if the positioning of the braces are different).
Forget braces. Consider languages with begin
/end
keywords and languages like Python.
The consistent statement across all those styles is that blocks need indentation. But they all allow for statements which modify the current block, such as using
, package
, program
, var
, etc.
And, as i pointed out, that's not universally true. There are already cases today (pun intended) where many do not indent the contents of a block. I see no reason why that is a place where people can have different conventions, but namespaces are somehow sacrosanct and must always be indented.
If you want C# to have a dialect where people don't indent namespaces, just create that dialect. There's no need for new syntax to enable what is just an affect of your editor.
I have never written switch
blocks with cases that line up with the switch, and I don't recall seeing code that does that. Surely that is an odd convention. At best it is an exception to the rule rather than the rule.
Besides, the contents of the case
would be indented, so it is a bit of a different thing anyway.
Spec: https://github.com/dotnet/csharplang/blob/main/proposals/csharp-10.0/file-scoped-namespaces.md
How it looks now:
Why do we need to nest our class definition in namespace ? Why not to remove extra nesting ? Isn't that better ?
LDM history: