A Pledge for Namespace Directives in C#

TradeNet (later TradeSoft), the company I worked for back in 2000 had me enrolled in a .NET Early Adopter Training Program which taught .NET Programming using a beta version of Visual Studio .NET.

I had mostly written code in Borland Delphi until then because of its rapid prototyping features for Windows applications, heck even for web applications. Delphi’s IDE was unmatched. The programming language it came with, Object Pascal, was clean for such a low-level one, had the right high-level constructs and abstractions in places and had a robust standard library called VCL. The only downside was manual memory management. Only alternatives with the same usability back then were Visual Basic and Java. Visual Basic didn’t have a good IDE and Java was slow as hell. Remember that this was back in 2000. Java lacked serious tooling too. It would still take another year before Java got a serious IDE called Eclipse.

Visual Studio .NET had shaken the throne of Delphi as Microsoft hired the Delphi’s locomotive force Anders Hejlsberg to design a new programming language called C#.

C# was what Object Pascal should have been: concise. Here is what a simple class looked like in Object Pascal if my memory serves me correctly:

unit MyUnit;interfacetype TMyClass = class(TObject)
procedure Hello(s:string);
end;
implementationprocedure TMyClass.Hello(s:string)
begin
WriteLn('Hello world ', s);
end;
end.

Too much noise, repetition of declarations, and too many keywords. C# version of it would look simpler which makes the actual code stand out more, and required you to type less too:

namespace MyNamespace
{
class MyClass
{
void Hello(string s)
{
Console.WriteLine($"Hello world {s}");
}
}
}

See, there is minimum amount of decoration. The code blocks are distinguishable yet easy on the eyes. The interface and implementation are in the same place to avoid duplication, albeit it’s arguable if that’s better or not. No frivolous keywords scattered around adding to the cognitive overload. Classes inherited Object class automatically. It’s a considerable improvement over Delphi. But is it an improvement over Java? See for yourself:

package MyPackage;class MyClass 
{
void Hello(string s)
{
System.out.format("Hello world %s", s);
}
}

Java version looks even simpler and cleaner than C# despite that I kept the Allman brace style for easier comparison. What makes the difference? Well, Java does not have namespace blocks. Instead, it has a “package” directive which applies a namespace declaration for the whole scope of the file.

C# set out to be a successor to Java with better features. Anders Hejlsberg added the right touches to the language which made it more practical such as properties andforeach statements in its first release. The team kept adding to the list of niceties in the following versions: type-inference, generics, lambda, LINQ, tuples, pattern matching, switch expressions, non-nullable references and so forth. Despite that it was released years before C#, Java has become the one that tries to catch up.

One of the handy additions to C# was the removing the restriction of “one-type per file” limit in Java. It was one of the archaic rules in Java, supposedly to encourage developers to program better. Well, using one file per type is usually good but having the option to keep a small type next to your class is great too. But it meant that a single file could contain classes from multiple namespaces, so namespaces had to have scopes. Scopes are defined by blocks, so we got namespace blocks.

Two words: unnecessary indentation. You need indentation to follow the structure and flow. However, a namespace contributes nothing in that aspect. Think about it: when was the last time did you have to have two different namespaces in a single file? What good would come from it? StyleCop already recommends single type per file, let alone namespaces.

But the greatest reason isn’t that, it’s the left margin. The left margin of a text editor is a greatly underestimated programming tool. When a text is right next to the left margin, you can easily say that it’s at the global scope. One indent in and you can say that you are inside a scope. But after the second indent, it becomes harder to track your contextual location in the source code. C# foregoes the benefits of the left margin from the day one, your code is always at least three indents in. Since it’s harder to discern between three and four indents than one and two, it’s easier to get clueless about whether the code is inside, say, a while or an if statement.

I know, the practices like writing the code in smaller chunks or returning early can help avoiding this problem but not altogether. You can always have the code at the top of the editor so it won’t matter how small your function is; you are still contextually lost. At least more so than one indent less.

Yes. That is easily one of the greatest and cheapest improvements to C#’s syntax. It is one of the things that Java got right. Why not change it to a directive and make it applicable to the file instead:

namespace My.Unique.Namespace;

That should have been done years ago. I know people carefully analyze risks versus benefits, backward compatibility, keeping it working with existing tools and whatnot. I can’t think of any sane reason to not improve upon that. Yes, I know that C# supports multiple classes and multiple namespaces per file so a “block-based” namespace syntax is required and I agree, to have backward compatibility or to address nested blocks or whatnot. But I think having mostly separate files for classes is helpful in larger projects.

I know that C# needs improvement on many fronts. It faces stiff competition in particular with the arrival of new generation languages like Go, Rust and Swift. C# can adopt better parallel processing paradigms like Goroutines, or stronger type systems or lifetime semantics as in Rust or better type-inference as in Swift. Heck, C# can even benefit a lot from “enums with methods”. But those require thorough analysis, careful decision-making not to dig yourself into a hole. I might say that’s exactly what D language has done. I admire C# team’s track record on their careful discretion on which features they bring into the ecosystem. Unfortunately, it also means that trivial stuff like optional namespace blocks might not make it into the language forever.

There is an open proposal for namespace directives. V̶o̶t̶e̶ ̶f̶o̶r̶ ̶i̶t̶.̶ (While I have been writing this article, uservoice is gone. So, just comment your support in the GitHub issue instead)

Writing Street Coder (https://www.manning.com/books/street-coder) · Ex-Software Engineer at Microsoft · Founder of eksisozluk.com · Demoscene old-timer

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store