56

I have a C++ background and I do fully understand and agree with the answers to this question: Why is “using namespace std;” considered bad practice?

So I'm astonished that, having some experience with C# now, I see the exact opposite there: using Some.Namespace; is literally used everywhere. Whenever you start using a type, you add a using directive for its namespace first (if it isn't there already). I cannot recall having seen a .cs-file that didn't start with using System; using System.Collections.Generic; using X.Y.Z; etc.... In fact, if you add a new file via the Visual Studio wizard, it automatically adds some using directives there, even though you may not need them at all. So, while in the C++ community you get basically lynched, C# even encourages doing this. At least this is how it appears to me.

Now, I do understand that using directives in C# and C++ are not exactly the same thing. Also, I do understand that one of the nastiest things you can do with using namespace in C++, namely putting it in a header file, has no equivalently nasty counterpart in C# due to the lack of a concept of header files and #include.

However, despite their differences, using directives in C# and C++ serve the same purpose, which is only having to type SomeType all the time, rather than the much longer Some.Namespace.SomeType (in C++ with :: instead of .). And with this same purpose, also the danger appears to be the same to me: naming collisions.

In the best case this results in a compilation error, so you "only" have to fix it. In the worst case, it still compiles and the code silently does different things than you intended it to do. So my question is: Why (apparently) are using directives considered so unequally bad in C# and C++?

Some ideas of an answer that I have (none of these really satisfy me, though):

  • Namespaces tend to be much longer and much more nested in C# than in C++ (std vs. System.Collection.Generic). So, there is more desire and more gain in de-noising the code this way. But even if this is true, this argument only applies when we look at the standard namespaces. Custom ones can have any short name you like, in both C# and C++.

  • Namespaces appear to be much more "fine granular" in C# than in C++. As an example, in C++ the entire standard library is contained in std (plus some tiny nested namespaces like chrono) while in C# you have System.IO, System.Threading, System.Text etc. So, the risk of having naming collisions is smaller. However, this is only a gut feeling. I didn't actually count how many names you "import" with using namespace std and using System. And again, even if this is true, this argument applies only when looking at the standard namespaces. Your own ones can be designed as fine granular as you wish, in both C# and C++.

Are there more arguments? I'm especially interested in actual hard facts (if there are any) and not so much in opinions.

sebrockm
  • 5,733
  • 2
  • 16
  • 39
  • @ChrisMM no, I'm really talking about C++, not C++cli – sebrockm Feb 03 '20 at 16:03
  • Nesting and fine granularity alone are a sufficient answer as far as I’m concerned. There are added reasons because C# files tend to be smaller in my experience, so scope is more limited, and overload resolution and name lookup happens in a *much* more straightforward fashion than in C++. – Konrad Rudolph Feb 03 '20 at 16:03
  • @sebrockm, the question really isn't about C++ at all. It's just comparing to C++'s `using namespace`. C++/CLI has the same `using` as C# though. – ChrisMM Feb 03 '20 at 16:04
  • @ChrisMM right, I still thought it's a good idea to attract people that have both, C++ and C# knowledge. Anyway, if it's not about "attracting people" but purely about content, then I can live with removing the C++ tag. However, I don't see why I should add C++/CLI... then I could as well add Visual Basic – sebrockm Feb 03 '20 at 16:09
  • 2
    @Timo The OP is explicitly *not* asking about header pollution. – Konrad Rudolph Feb 03 '20 at 16:10
  • Namespaces were not in C++ from the beginning. They were added in C++95. As such there was a large body of existing namespace codebase. This includes the C library. This results in a much larger impact of "using namespace", than it otherwise would be. – Sam Varshavchik Feb 03 '20 at 16:11
  • @sebrockm, I understand. I think the problem is mainly that they are two very different languages, so a C++ reason for not `using namespace` doesn't necessarily apply to C#'s `using` statement. In C++, for example, `std` is used for nearly all functions in the standard, with some being nested in their own inner namespaces. In C#, it's the opposite (from what I remember), where most things reside in nested namespaces, and not (too) much in `System` itself. I think that `using namespace std` will give a lot more name-collisions compared to `System` – ChrisMM Feb 03 '20 at 16:14
  • @ChrisMM that's precisely what I wrote in the second bullet point at the end of my question :) – sebrockm Feb 03 '20 at 16:19
  • 1
    I assumed it was because there's no competition for the global namespace to the same degree that there is in C++ (primarily due to the C standard library). But I await the answers of those who know best. – Wyck Feb 03 '20 at 16:20
  • @sebrockm, yes, and I think you nailed it with that statement. But that's just my opinion. – ChrisMM Feb 03 '20 at 16:20
  • 2
    @ThomasWeller In C++ it's obvious. In C# consider an extensions method with `Ext(this T t, long l)` that is called via `t.Ext(0)`. If you then add another namespace that contains an extension method `Ext(this T t, int i)`, that one will be called instead. But I'm not an expert in C# (yet). – sebrockm Feb 03 '20 at 16:22
  • 1
    Can you have a `using` statement in local scopes? In C++ you can put a `using` in the function scope or class definition scope. Is this allowed in C#? In addition, you don't often encounter very long qualifiers for identifiers. For example, the most common is `std::` which is brief and obstructive. It might just be that the longer qualifiers in C# make `using` more attractive there. – François Andrieux Feb 03 '20 at 16:28
  • @sebrockm Just noticed after the fact the types were different but in that case yes but that is not an issue about usings. If you want to call the `long` version you call `t.ext(0L)` that is just basic overriding. If 2 methods or object have the same name/signature in C# it wont let you compile. It will complain about ambiguous call and ask for precision if you meant to call `namespace1.A` or `namespace2.A` – Franck Feb 03 '20 at 16:28
  • 1
    @sebrockm your point is valid. You will get an overload of that extension method (even if they're defined in different namespaces). No warnings will be generated. – Timo Feb 03 '20 at 16:29
  • @Franck well, than that's my point. You due to using another namespace you get another overload that is a better match and thus your code will silently change what it does. – sebrockm Feb 03 '20 at 16:31
  • @sebrockm but this issue is the job of unit testing. If you coded it and passed an `int` to a method requiring a `long` it's the developer problem. If i have a square hole and always passed a round ball through it because it fits it is bas coding or bad design. the hole should have been round to begin with. – Franck Feb 03 '20 at 16:33
  • 2
    @Franck even if I granted you that point, then the same argument applies to C++, further pushing my question of not seeing the difference between C++ and C# – sebrockm Feb 03 '20 at 16:35
  • @sebrockm If it recall correctly C++ won't warn you at all for same signature. It will take the one from the first loaded header and that's it. That is a very dangerous behavior for C++ as you need to manually track everything to make sure it pointing to the right place. – Franck Feb 03 '20 at 16:37
  • 3
    @Franck C++ will throw a compiler error at you in case of ambiguity. As well as C#. – Timo Feb 03 '20 at 16:39
  • @Timo thanks for clarification. Haven't touch C++ in 2-3 years. The only issue i see in this is ambiguity of calls so if that's well implemented in both case i don't see why it can be an issue. – Franck Feb 03 '20 at 16:43
  • I don't see the point, why someone could be disturbed in any way, by having "too much" usings. You don't look there, it doesn't influence readability negatively, if something is ambiguous the compiler will tell you. There is even a "Remove Unnecessary usings" Command built-in, in VS. No negative side effect anywhere. You can rather discuss if "using static" is helpful or disturbing. It can be both. When I'm unsure of a namespace I do "Go to definition" or sometimes just hoover over it, and I will see it's origin. There is not just the plain text available, when reading code. – Holger Feb 03 '20 at 17:22
  • @Holger At least half your comment is based on faulty assumptions, as has been discussed *ad nauseam* in the previous comments. – Konrad Rudolph Feb 03 '20 at 23:27
  • @KonradRudolph It's opinion-based, opinion is never faulty. Words like "readable", recognize, informative, didn't appear anywhere. It's just beyond my imagination, how one can be disturbed by one or more lines on the edge of perception. If it compiles, all possible ambiguity arguments are meaningless.Nobody discussed if you insert System.Collection.Generic forward looking, when creating the file, or just in the second, then you type new List. In neither case you type it, in both cases it's generated for you with one click. – Holger Feb 04 '20 at 09:35
  • @Holger “opinion based” is too often an excuse for lack of arguments. “no negative side effects anywhere” and “if something is ambiguous the compiler will tell you” are not opinions, they are claims of fact, and they are both demonstrably false, as previous comments have explained. – Konrad Rudolph Feb 04 '20 at 09:45
  • @KonradRudolph There cannot be arguments, if there is no problem. Human perception wasn't a topic anywhere. Compiler detectable side effects are no side effects, cause they exists only for seconds - until you correct it. Modification of code may cause change of behaviour. That's not really a genious finding. Especially in this case it's not telling you if remove or insert is better. It's the change that causes possible trouble, not the direction of change. Would you please stop telling me "shut-up" cause this is strongly opinion-based also. – Holger Feb 04 '20 at 09:55
  • 1
    Please read other (less upvoted) answers in your linked questions, and you'll see that `using namespace` is not considered bad in every usage by some folks. Read https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#Rs-using and https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#Rs-using-directive. – geza Feb 04 '20 at 11:13
  • 1
    I have written C# code for many years. I have no idea how many C# files I have created but it must thousands upon thousands. I have **never** had any issues with "too many using" statements. – Martin Liversage Feb 04 '20 at 11:15
  • @KonradRudolph You have not named a single failure, you permanently just repeat I'm globally wrong, and should go and read to find out where I'm wrong, you are unwilling to point it out - you discredit people - not their statements. The possibility of trouble is not a reason not to do something, as the possibility of fire is not a reason, not to build a house from wood. You can always prevent risks, or handle them if they occur. Decision depends on cost and possibility. – Holger Feb 04 '20 at 11:31
  • @MartinLiversage Well, the question is not necessarily about "too many" usings, rather about why the C# and the C++ people's mindsets are so different. – sebrockm Feb 04 '20 at 11:34
  • @geza that's a very good point. Thanks for pointing it out. – sebrockm Feb 04 '20 at 11:43
  • 1
    @sebrockm: I think that `using namespace` is not always a bad practice. C++ people tend to be over-cautious (just because there can be problems about it in certain situations, it doesn't mean that it has to be always banned). `using namespace` is a tool, which has pros/cons, and one has to learn when to use it. It's easier to learn "`using namespace` is bad practice" than to learn which are the cases when it's OK. Also don't be mislead by the "most upvoted answer is the best answer". Usually that's the case, but there are cases where it is debatable... – geza Feb 04 '20 at 14:30

2 Answers2

35

Why is “using System;” not considered bad practice?

"using System;" is not universally not considered a bad practice. See for example: Why would you not use the 'using' directive in C#?

But it may be true that it is not considered quite as bad as using namespace std. Probably because:

  1. C# does not have header files. It is uncommon to "include" one C# source file into another using a pre-processor.

  2. std namespace is nearly flat i.e. almost all standard library functions, types and variables are in it (there are few exceptions such as the filesystem sub-namespace). It contains very, very high number of identifiers. To my understanding, System contains much fewer names, and instead has more sub-namespaces.

  3. In C#, there are no global functions or variables. As such, the number of global identifiers is typically quite small in contrast to C++ which does have those: Furthermore, it is typical to use C libraries (often indirectly) which doesn't have namespaces, and therefore place all their names into the global namespace.

  4. As far as I know, C# has no argument dependent lookup. ADL in conjunction with name hiding, overloading etc. can produce cases where some programs are not affected by a name conflict, while others are subtly affected, and catching all corner cases is not feasible with testing.

Because of these differences, “using System;” has lower chance of name conflict than using namespace std.


Also, namespace "importing" is in a way, a self-perpetuating convention: If it is conventional to import a standard namespace, then programmers will conventionally try to avoid choosing names from that namespace for their own identifiers, which helps to reduce problems with such convention.

If such an import is considered a bad practice, then programmers will be less likely to even attempt such avoidance of conflicts with imported namespaces. As such, conventions tend to get polarised either for or against the practice, even if weights of arguments between the choices were originally subtle.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
eerorika
  • 232,697
  • 12
  • 197
  • 326
  • 4
    This considers only potential drawbacks of opening namespaces. That’s a start, but I think we also need to consider the advantages: in the case of C++, in most cases it’s saving five characters (`std::`). In C#, it’s substantially more (`System.` has “only” 7 characters, but other, nested namespaces have *many* more characters, and writing them out everywhere would make code completely unreadable). – Konrad Rudolph Feb 03 '20 at 16:48
  • Isn't it the case also that C# overload resolution is kinder than the one in C++ and a lot of ambiguity is drawn out via compiler errors? (By no means a criticism of your answer which seems authoritative.) – Bathsheba Feb 03 '20 at 16:50
  • 4
    @KonradRudolph If the drawbacks were considered significant, and the amount of typing equally so (compared to amount of typing `std::`), would it not be typical style to use `using Sys = System;` instead the namespace polluting non-alias `using`? – eerorika Feb 03 '20 at 17:02
  • 2
    @Bathsheba regarding "authoritative", I'd like to disclaim that I know very little about C#, and my answer is based on knowledge of C++, and a few google searches about C#. So, I'd appreciate if someone fact checks the C# parts :) – eerorika Feb 03 '20 at 17:07
  • @eerorika Maybe. But it’s just one more argument that is tipping the scales in favour of `using`, in combination with the other arguments. – Konrad Rudolph Feb 03 '20 at 17:08
  • 2
    Regarding the ADL part: C# has extension methods. It's a different design than ADL, but they share the same problems regarding naming conflicts. – Timo Feb 03 '20 at 17:18
-2

However, despite their differences, using directives in C# and C++ serve the same purpose, which is only having to type SomeType all the time, rather than the much longer Some.Namespace.SomeType (in C++ with :: instead of .). And with this same purpose, also the danger appears to be theto me: naming collisions.

Yes, but you didn't export that danger (read: forcing others to deal with it), because of:

Now, I do understand that using directives in C# and C++ are not exactly the same thing. Also, I do understand that one of the most nasty things you can do with using namespace in C++, namely putting it in a header file, has no equivalent in C# due to the lack of a concept of header files and #include.

So it's rather a different category of thing.

Also, C++ is not "designed" to be developed in an IDE the same way C# is. C# is basically always written in Visual Studio with its Intellisense and whatnot. It's designed to be used that way, by the people who created it. Regardless of how many people use an IDE to develop in C++, it is not designed with that use case as an overwhelming concern.

Namespaces appear to be much more "fine granular" in C# than in C++.

Yes, that too. using namespace std and using System.Collection.Generic are incomparable.

So don't compare them!

Asteroids With Wings
  • 17,071
  • 2
  • 21
  • 35
  • 2
    This doesn’t answer OP’s concern, which is explicitly *not* about opening namespaces in headers, but in *implementation files*. – Konrad Rudolph Feb 03 '20 at 16:09
  • 2
    @KonradRudolph The advice to avoid `using namespace std` in C++ is mostly about header files. The answer _is_ that this does not apply in C#. – Asteroids With Wings Feb 03 '20 at 16:11
  • 9
    @AsteroidsWithWings the advice to avoid `using namespace std` is certainly not mostly about headers. Using it in headers is dangerous. Using it in your implementations is adviced against. – Tommy Andersen Feb 03 '20 at 16:12
  • 1
    The advice to avoid `using namespace ...` in c++ is about avoiding naming collision, the `using` directive in C# introduce the possibility of naming collision as well, then why not avoid it? Even though there implementation differ. – Tommy Andersen Feb 03 '20 at 16:22
  • @TommyAndersen, how difficult is it to resolve such conflict if it happens? It takes a second. Since C# `using` declarations are per file that defines single type/class and the type normally has to do with a relatively narrow set of application domain concepts (ideally, single responsibility principle) probability of such namespace clashes is extremely low. But when happen are easily fixable. Common .NET development tools/IDE help you a lot with that. Consider the whole development ecosystem that is designed to make you more productive by combining the best of multiple development activities – AKornich Feb 04 '20 at 21:08