4

One thing I do not get with C#'s using Directive is why I can only "use" a namespace at file level, and not within any arbitrary block scope.

(using namespace x; of C++ does allow this and certainly the C# designers where aware of this.)

If I have, e.g., one single function in my class that does something with file I/O, it seems to me it would make sense to just write:

void MunchFile(string name) {
  using System.IO; // not allowed
  ...
}

but instead I have to write:

// somewhere at the top of the file:
using System.IO;
... 2 pages down ...
    void MunchFile(string name) {
      ...
    }

It's an irritation every time I encounter it and I keep scratching my head why this was not allowed / implemented.

So:

  • Are there any statements by C# designers wrt. this?
  • Is there any conceptual language design issue wrt. this?
  • 6
    I find your proposal horrendous. Confining using directives at the top of the file (instead of scattering them throughout the file) is a much better approach. if you feel compelled to use qualified namespace names in the middle of your file, just say System.IO.File.[Whatever] instead. – Robert Harvey Apr 7 '16 at 21:06
  • @Robert - Ah! So you're one of those that also likes to declare all local variables at the top of the function because it's such a hassle if they are scattered all over the function? :-P ;-) ... Both you and svidgen seem to think this useless, so there's that and I can't really argue other than I think it's not. But "horrendous"? Nah. – Martin Ba Apr 8 '16 at 7:52
  • 2
    A namespace is not a variable ... It cannot be assigned to or directly referred to after being declared. It simply exposes names within that space to the context. There's absolutely not reason to conclude that @RobertHarvey would treat his variables identically to his namespaces. There's also no reason to believe that a language should do so. – svidgen Apr 8 '16 at 13:56
  • @Martin Ba: I find your example a bit weird. Usually, a class that does file IO does it a lot, so if you have a situation where your using directive is not actually used till two pages lower, maybe you should either move all files related actions to another class – BgrWorker Apr 8 '16 at 19:49
2

While he doesn't refer specifically to the using directive, Eric Gunnerson's article Minus 100 Points addresses the general question of "why doesn't C# have [feature X] which C++ has". The most relevant part reads:

That wording implies that we started with an existing language (C++ and Java are the popular choices here), and then started removing features until we got to a point where we liked. And, though it may be hard for some to believe, that’s not how the language got designed.

One of the big reasons we didn’t do this is that it’s really hard to remove complexity when you take a subtractive approach, as removing a feature in one area may not allow you to revisit low-level design decisions, nor will it allow you to remove complexity elsewhere, in places where it support the now-removed feature.

So, we decided on the additive approach instead, and worked hard to keep the complexity down.

He goes on to describe how the importance of a feature can be weighed against the complexity it introduces. Long story short, a lot of features that other languages have didn't make the cut, because the results they achieve simply aren't compelling enough for a language whose designers were aiming at simplicity.

5

Because, the proposed feature is a little silly.

Namespaces exist specifically to avoid naming conflicts. The using exists to DRY your code. It allows the omission of namespace prefixes for items therein that don't actually conflict with anything.

That said, if there is no name conflict at the top level, you can put the namespace at the top. There's no reason not to simply put it at the top! And then the whole file is a little DRY-er.

In the usual cases, if there is a conflict, adding a namespace to a nested scope doesn't eliminate the conflict.

using Collections.Or.Something;

public void UseAMagicalListForSomething()
{
    using My.Own.Magical.Collections;
    var myMagicalList = new List<OfWhatever>(); // STILL ambiguous.
}

You would still need to use the fully qualified class name:

using Collections.Or.Something;

public void UseAMagicalListForSomething()
{
    // lengthy, but unambiguous.
    var myMagicalList = My.Own.Magical.Collections.List<OfWhatever>();
}

Or specify an alias, which you can easily do at the top:

using Collections.Or.Something;
using magic = My.Own.Magical.Collections;

public void UseAMagicalListForSomething()
{
    var myMagicalList = magic.List<OfWhatever>(); // unambiguous.
}

The single case where the proposed feature could resolve a naming conflict and successfully DRY your code, would be if you happen to have two non-overlapping blocks of code in the same file.

However, if those non-overlapping blocks of code are using entirely different namespaces, I'd take a step back and question whether they really belong in the same file. If they really do, I'd argue that it's better to make the relationship between those blocks and the global scope clear with namespace aliases.

  • But if the two using directives were needed only in separate, non-overlapping blocks, then this idea would remove the conflict. Not saying it's a good idea, but it would remove the issue in some (probably fairly rare) cases. – Philip Kendall Apr 7 '16 at 21:53
  • @PhilipKendall Agreed. If I have time tomorrow when I'm back at the office, I'll make a note of that in my answer somehow. – svidgen Apr 8 '16 at 4:28
  • Note that this is not about avoiding conflicts, but about introducing names in as narrow a scope as possible. I do not use a member variable when a local suffices. So why would I make a namespace visible in the whole file, if only a tiny portion of the file needs it? – Martin Ba Apr 8 '16 at 7:54
  • 2
    @MartinBa Your question may not be directly about avoiding conflicts, but namespaces exist to avoid conflicts. That's their purpose. So, the only reason you wouldn't simply define it at the top in most cases would to be avoid conflicts between namespaces. Philip points out one case where block-level namespaces might be helpful ... but it's probably only relevant if your code is horrendous! – svidgen Apr 8 '16 at 14:00
  • That doesn't address extension methods. They cannot be qualified and therefore force-require the using. when we otherwise wouldn't want the namespace to be active elsewhere than just this small bloc. – v.oddou Sep 16 '16 at 2:39
-1

There are a few reasons it may not have been allowed in C#.

  1. It makes it easier to see what namespaces are being used if they are all in a centralized area.

  2. It is much easier to declare the using in one location if you want to use it in multiple methods.

  3. Pretty much every IDE I have worked with and VS in particular will tell you the fully qualified name of a type if you hover the cursor over it. Therefore even if it is two pages of code down from the using statement the name is allows easy to discover quickly.

  4. The using statement can already appear in methods to help assist with object disposal (ex. closing file streams) so it being context sensitive to that case may prevent it from even being possible to implement now.

  • this post is rather hard to read (wall of text). Would you mind editing it into a better shape? – gnat Apr 8 '16 at 14:37

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.