C# – Why Avoid Using the ‘using’ Directive?

ccoding-standards

The existing coding standards on a large C# project includes a rule that all type names be fully qualified, forbidding employment of the 'using' directive. So, rather than the familiar:

using System.Collections.Generic;

.... other stuff ....

List<string> myList = new List<string>();

(It's probably no surprise that var also is prohibited.)

I end up with:

System.Collections.Generic.List<string> myList = new System.Collections.Generic.List<string>();

That's a 134% increase in typing, with none of that increase providing useful information. In my view, 100% of the increase is noise (clutter) that actually impedes understanding.

In 30+ years of programming, I've seen such a standard proposed once or twice, but never implemented. The rationale behind it escapes me. The person imposing the standard is not stupid, and I don't think he's malicious. Which leaves misguided as the only other alternative unless I'm missing something.

Have you ever heard of such a standard being imposed? If so, what was the reason behind it? Can you think of arguments other than "it's stupid," or "everybody else employs using" that might convince this person to remove this prohibition?

Reasoning

The reasons for this prohibition were:

  1. It's cumbersome to hover the mouse over the name to get the fully qualified type. It's better to always have the fully qualified type visible all the time.
  2. Emailed code snippets don't have the fully qualified name, and therefore can be difficult to understand.
  3. When viewing or editing the code outside of Visual Studio (Notepad++, for example), it's impossible to get the fully qualified type name.

My contention is that all three cases are rare, and that making everybody pay the price of cluttered and less-understandable code just to accommodate a few rare cases is misguided.

Potential namespace conflict issues, which I expected to be the primary concern, weren't even mentioned. That's especially surprising because we have a namespace, MyCompany.MyProject.Core, which is an especially bad idea. I learned long ago that naming anything System or Core in C# is a quick path to insanity.

As others have pointed out, namespace conflicts are easily handled by refactoring, namespace aliases, or partial qualification.

Best Answer

The broader question:

Have you ever heard of such a standard being imposed? If so, what was the reason behind it?

Yes, I've heard of this, and using fully qualified object names prevents name collisions. Though rare, when they happen, they can be exceptionally thorny to figure out.


An Example: That type of a scenario is probably better explained with an example.

Let's say we have two Lists<T> belonging to two separate projects.

System.Collections.Generic.List<T>
MyCorp.CustomCollections.Optimized.List<T>

When we use the fully qualified object name, it's clear as to which List<T> is being used. That clarity obviously comes at the cost of verbosity.

And you might be arguing, "Wait! No one would ever use two lists like that!" Which is where I'll point out the maintenance scenario.

You've written module Foo for your corporation which uses the corporation approved, optimized List<T>.

using MyCorp.CustomCollections.Optimized;

public class Foo {
    List<object> myList = ...;
}

Later on, a new developer decides to extend the work you've been doing. Not being aware of the company's standards, they update the using block:

using MyCorp.CustomCollections.Optimized;
using System.Collections.Generic;

And you can see how things go bad in a hurry.

It should be trivial to point out that you could have two proprietary classes of the same name but in different namespaces within the same project. So it's not just a concern about colliding with .NET Framework supplied classes.

MyCorp.WeightsAndLengths.Measurement();
MyCorp.TimeAndSpace.Measurement();

The reality:
Now, is this likely to occur in most projects? No, not really. But when you're working on a large project with a lot of inputs, you do your best to minimize the chances of things exploding on you.

Large projects with multiple contributing teams are a special kind of beast in the application world. Rules that seem unreasonable for other projects become more pertinent due to the input streams to the project and the likelihood that those contributing haven't read the project's guidelines.

This can also occur when two large projects are merged together. If both projects had similarly named classes, then you'll see collisions when you start referencing from one project to the other. And the projects may be too large to refactor or management won't approve the expense to fund the time spent on refactoring.


Alternatives:
While you didn't ask, it's worth pointing out that this is not a great solution to the problem. It's not a good idea to be creating classes that will collide without their namespace declarations.

List<T>, in particular, ought to be treated as a reserved word and not used as the name for your classes.

Likewise, individual namespaces within the project should strive to have unique class names. Having to try and recall which namespace's Foo() you're working with is mental overhead that is best avoided. Said another way: having MyCorp.Bar.Foo() and MyCorp.Baz.Foo() is going to trip your developers up and best avoided.

If nothing else, you can use partial namespaces in order to resolve the ambiguity. For example, if you absolutely can't rename either Foo() class you could use their partial namespaces:

Bar.Foo() 
Baz.Foo()

Specific reasons for your current project:

You updated your question with the specific reasons you were given for your current project following that standard. Let's take a look at them and really digress down the bunny trail.

It's cumbersome to hover the mouse over the name to get the fully qualified type. It's better to always have the fully qualified type visible all the time.

"Cumbersome?" Um, no. Annoying perhaps. Moving a few ounces of plastic in order to shift an on-screen pointer is not cumbersome. But I digress.

This line of reasoning seems more like a cover-up than anything else. Offhand, I'd guess that the classes within the application are weakly named and you have to rely upon the namespace in order to glean the appropriate amount of semantic information surrounding the class name.

This is not a valid justification for fully qualified class names, perhaps it's a valid justification for using partially qualified class names.

Emailed code snippets don't have the fully qualified name, and therefore can be difficult to understand.

This (continued?) line of reasoning reinforces my suspicion that classes are currently poorly named. Again, having poor class names is not a good justification for requiring everything to use a fully qualified class name. If the class name is difficult to understand, there's a lot more wrong than what fully qualified class names can fix.

When viewing or editing the code outside of Visual Studio (Notepad++, for example), it's impossible to get the fully qualified type name.

Of all the reasons, this one nearly made me spit out my drink. But again, I digress.

I'm left wondering why is the team frequently editing or viewing code outside of Visual Studio? And now we're looking at a justification that's pretty well orthogonal to what namespaces are meant to provide. This is a tooling backed argument whereas namespaces are there to provide organizational structure to the code.

It sounds like the project you own suffers from poor naming conventions along with developers who aren't taking advantage of what the tooling can provide for them. And rather than resolve those actual issues, they attempt to slap a band-aid over one of the symptoms and are requiring fully qualified class names. I think it's safe to categorize this as a misguided approach.

Given that there are poorly named classes, and assuming you can't refactor, the correct answer is to use the Visual Studio IDE to its full advantage. Possibly consider adding in a plugin like the VS PowerTools package. Then, when I'm looking at AtrociouslyNamedClass() I can click on the class name, press F12 and be taken directly to the definition of the class in order to better understand what it's trying to do. Likewise, I can press Shift-F12 to find all the spots in the code currently suffering from having to use AtrociouslyNamedClass().

Regarding the outside tooling concerns - the best thing to do is to just stop it. Don't email snippets back and forth if they aren't immediately clear what they refer to. Don't use other tools outside of Visual Studio as those tools don't have the intelligence surrounding the code that your team needs. Notepad++ is an awesome tool, but it's not cut out for this task.

So I agree with your assessment regarding the three specific justifications you were presented with. That said, what I think you were told was "We have underlying issues on this project that can't / won't address and this is how we 'fixed' them." And that obviously speaks to deeper issues within the team that may serve as red flags for you.

Related Topic