为什么是“使用系统”;不算作坏习惯吗?


47

我具有C ++背景,并且我完全理解并同意以下问题的答案:为什么“使用命名空间标准”;被认为是不良做法?

因此,令我惊讶的是,现在已经有了C#的经验,我看到了与之完全相反的地方: using Some.Namespace;确实在任何地方都使用过。无论何时开始使用类型,都首先为其名称空间添加using指令(如果尚不存在)。我不记得曾经看到过一个.cs不是以-开头的文件using System; using System.Collections.Generic; using X.Y.Z; etc...。实际上,如果您通过Visual Studio向导添加了新文件,即使您根本不需要它们,它也会在其中自动添加一些using指令。因此,尽管在C ++社区中您基本上被私刑了,但C#甚至鼓励这样做。至少我是这样。

现在,我知道在C#和C ++中使用指令并不完全相同。另外,我确实知道,using namespace在C ++中可以做的最讨厌的事情之一,即将其放入头文件中,由于缺少头文件和的概念,因此在C#中没有同等讨厌的对象#include

但是,尽管它们有所不同,但在C#和C ++中使用伪指令却达到了相同的目的,即仅需SomeType始终键入,而不必花更长的时间Some.Namespace.SomeType(在C ++中使用::代替.)。出于同样的目的,危险对我来说似乎也一样:命名碰撞。

在最佳情况下,这会导致编译错误,因此您“仅”必须进行修复。在最坏的情况下,它仍然会编译,并且代码会静默地执行与您预期的不同的操作。所以我的问题是:为什么(显然)使用的指令在C#和C ++中被认为是同等糟糕的?

我有一些答案的想法(尽管这些想法都没有真正让我满意):

  • 命名空间趋向于更长和更嵌套在C#比在C ++(std对比System.Collection.Generic)。因此,以这种方式对代码进行降噪会有更多的愿望和收获。但是,即使这是真的,该参数也仅在我们查看标准名称空间时适用。自定义名称可以在C#和C ++中具有您喜欢的任何短名称。

  • 在C#中,命名空间似乎比在C ++中更“精细”。举个例子,在C ++整个标准库包含在std(加上一些微小的嵌套的命名空间一样chrono),而在C#中你有System.IOSystem.ThreadingSystem.Text等,所以,其命名冲突的风险较小。但是,这只是一种直觉。实际上,我没有计算您使用using namespace std和导入的名称using System。同样,即使这是正确的,此参数也仅在查看标准名称空间时适用。您可以在C#和C ++中将自己的代码设计为细粒度。

还有更多争论吗?我对实际的硬事实(如果有的话)特别感兴趣,而对观点却不太感兴趣。


2
@Timo OP明确没有询问头污染。
Konrad Rudolph

1
我以为是因为没有像C ++那样竞争全局名称空间(主要是由于C标准库)。但我等待最了解的人的回答。
Wyck

2
@ThomasWeller在C ++中很明显。在C#中,请考虑Ext(this T t, long l)通过调用的扩展方法t.Ext(0)。如果然后添加另一个包含扩展方法的名称空间,Ext(this T t, int i)则将改为调用该名称空间。但是我还不是C#的专家(尚未)。
sebrockm

2
@Franck即使我同意了这一点,但同样的论点也适用于C ++,进一步推动了我的问题,即看不到C ++和C#之间的区别
sebrockm

3
如果出现歧义,@ Franck C ++将向您抛出编译器错误。以及C#。
蒂莫

Answers:


28

为什么是“使用系统”;不算作坏习惯吗?

“使用系统”;是不是普遍不被认为是不好的做法。例如,请参见:为什么不在C#中使用'using'指令?

但是确实可以认为它并不像坏的那样using namespace std。可能是因为:

  1. C#没有头文件。使用预处理器将一个C#源文件“包含”到另一个C#源文件中是不常见的。

  2. std名称空间几乎是平坦的,即几乎所有标准库函数,类型和变量都在其中(几乎没有例外,例如文件系统子名称空间)。它包含非常多的标识符。据我了解, System包含的名称要少得多,而具有更多的子命名空间。

  3. 在C#中,没有全局函数或变量。因此,与具有这些标识符的C ++相比,全局标识符的数量通常非常小:此外,通常使用不带名称空间的C库(通常是间接使用),因此将其所有名称放入全局命名空间。

  4. 据我所知,C#没有依赖于参数的查找。ADL与名称隐藏,重载等结合可能会导致某些程序不受名称冲突影响,而其他程序受到微妙影响的情况,并且在测试中无法捕获所有极端情况。

由于存在这些差异,因此“使用系统” 名称冲突的可能性比更低using namespace std


同样,名称空间“导入”在某种程度上是一种永续的约定:如果惯例是导入标准名称空间,则程序员通常会尝试避免从该名称空间中为自己的标识符选择名称,这有助于减少与这样的约定。

如果认为这种导入是不好的做法,那么程序员甚至不太可能尝试避免与导入的名称空间发生冲突。这样一来,即使选择之间的论据权重本来就很微妙,惯例还是倾向于对实践持反对意见或反对态度。


3
这仅考虑了打开名称空间的潜在缺点。这是一个开始,但是我认为我们还需要考虑其优势:对于C ++,在大多数情况下,它节省了五个字符(std::)。在C#中,它的多得多(System.“仅” 7个字符,但其他的,嵌套的命名空间有有很多更多的字符,写他们无处不出来会使代码完全不可读)。
Konrad Rudolph

C#重载分辨率比C ++中的重载分辨率还好,并且通过编译器错误引起很多歧义吗?(决不批评您的回答似乎权威。)
Bathsheba

3
@KonradRudolph如果认为缺点很明显,并且打字量也是如此(与打字量相比std::),那么使用using Sys = System;命名空间污染非别名不是典型的样式using吗?
eerorika

2
@Bathsheba关于“权威”,我想否认自己对C#知之甚少,我的答案是基于C ++的知识,还有一些Google搜索有关C#的内容。因此,如果有人检查了C#部分,我将不胜感激:)
eerorika

2
关于ADL部分:C#具有扩展方法。它与ADL的设计不同,但是它们在命名冲突方面存在相同的问题。
蒂莫

-2

但是,尽管它们有所不同,但在C#和C ++中使用伪指令却达到了相同的目的,只需要始终键入SomeType,而不是更长的Some.Namespace.SomeType(在C ++中使用::代替。)。出于同样的目的,危险似乎也就在于我:命名冲突。

是的,但是您没有导出该危险(请参阅:强迫其他人应对),原因是:

现在,我知道在C#和C ++中使用指令并不完全相同。另外,我确实了解到,在C ++中使用名称空间可以做的最讨厌的事情之一,即将其放入头文件中,由于缺少头文件和#include的概念,因此在C#中没有等效项。

所以这是另一种类别的事情。

同样,C ++并非“设计”为以与C#相同的方式在IDE中开发。C#基本上总是使用Visual Studio的Intellisense和诸如此类的东西编写。它被设计为由创建它的人使用。不管有多少人使用IDE来进行C ++开发,在设计该用例时都不会将其作为压倒一切的考虑。

在C#中,命名空间似乎比在C ++中更“精细”。

是的,那也是。using namespace std而且using System.Collection.Generic是无与伦比的。

所以不要比较它们!


2
这并不能解决OP的问题,因为这显然不是关于在标头中打开名称空间,而是在实现文件中
Konrad Rudolph

2
@KonradRudolph using namespace std在C ++中应避免的建议主要是关于头文件。答案,这不适用于C#。
带翅膀的小行星

8
@AsteroidsWithWings避免的建议using namespace std当然主要不是关于标题。在标题中使用它是危险的。建议在您的实现中使用它。
Tommy Andersen

1
using namespace ...在c ++中应避免的建议是避免命名冲突,usingC#中的指令也引入了命名冲突的可能性,那么为什么不避免呢?即使实现不同。
Tommy Andersen

@TommyAndersen,如果发生这种冲突,解决它有多困难?需要一秒钟。由于C# using声明是每个文件定义单个类型/类的,并且该类型通常与相对狭窄的一组应用程序域概念(理想情况下是单责任原则)有关,因此此类名称空间冲突的可能性极低。但是发生的时候很容易修复。通用的.NET开发工具/ IDE可以为您提供很多帮助。考虑整个开发生态系统,该生态系统旨在通过结合最佳的多个开发活动来提高您的生产率
AKornich
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.