c# - 为什么是“使用系统”;不被认为是不好的做法?
问题描述
我有 C++ 背景,我完全理解并同意这个问题的答案:Why is “using namespace std;” 被认为是不好的做法?
所以我很惊讶,现在有了一些 C# 经验,我看到了完全相反的情况:
using Some.Namespace;
字面上到处都在使用。每当你开始使用一个类型时,你首先为它的命名空间添加一个 using 指令(如果它还没有的话)。我不记得曾经看过一个.cs
不以using System; using System.Collections.Generic; using X.Y.Z; etc...
. 事实上,如果您通过 Visual Studio 向导添加一个新文件,它会自动在其中添加一些 using 指令,即使您可能根本不需要它们。因此,虽然在 C++ 社区中你基本上会被处以私刑,但 C# 甚至鼓励这样做。至少在我看来是这样的。
现在,我确实明白在 C# 和 C++ 中使用指令并不完全相同。另外,我确实理解在 C++ 中可以做的最using namespace
讨厌的事情之一,即把它放在头文件中,由于缺少头文件和#include
.
然而,尽管存在差异,但在 C# 和 C++ 中使用指令具有相同的目的,即只需要一直键入SomeType
,而不是更长的时间Some.Namespace.SomeType
(在 C++ 中使用::
而不是.
)。出于同样的目的,对我来说危险似乎也是一样的:命名冲突。
在最好的情况下,这会导致编译错误,因此您“只需”修复它。在最坏的情况下,它仍然可以编译,并且代码会默默地执行与您预期不同的事情。所以我的问题是:为什么(显然)使用在 C# 和 C++ 中被认为非常糟糕的指令?
我有一些关于答案的想法(不过,这些想法都不能让我满意):
命名空间在 C# 中往往比在 C++ 中更长且嵌套更多(
std
vs.System.Collection.Generic
)。因此,以这种方式对代码进行去噪有更多的愿望和更多的收获。但即使这是真的,这个论点也只适用于我们查看标准命名空间时。在 C# 和 C++ 中,自定义名称可以具有您喜欢的任何短名称。命名空间在 C# 中似乎比在 C++ 中更“细粒度”。例如,在 C++ 中,整个标准库都包含在
std
(加上一些小的嵌套命名空间,如chrono
),而在 C# 中,您有,System.IO
等。因此,发生命名冲突的风险较小。然而,这只是一种直觉。我实际上并没有计算你用and “导入”了多少个名字。同样,即使这是真的,这个论点也只适用于标准命名空间。在 C# 和 C++ 中,您自己的可以设计成您希望的细粒度。System.Threading
System.Text
using namespace std
using System
还有更多的争论吗?我对实际确凿的事实(如果有的话)特别感兴趣,而不是对意见感兴趣。
解决方案
为什么是“使用系统;” 不被认为是不好的做法?
“使用系统;” 并非普遍认为是不好的做法。例如,请参阅:为什么不在 C# 中使用“使用”指令?
但它可能没有被认为是那么糟糕using namespace std
。可能是因为:
C# 没有头文件。使用预处理器将一个 C# 源文件“包含”到另一个 C# 源文件是不常见的。
std
命名空间几乎是扁平的,即几乎所有标准库函数、类型和变量都在其中(很少有例外,例如文件系统子命名空间)。它包含非常非常多的标识符。据我了解,System
包含的名称要少得多,而具有更多的子命名空间。在 C# 中,没有全局函数或变量。因此,与确实有这些的 C++ 相比,全局标识符的数量通常非常少:此外,通常使用没有命名空间的 C 库(通常是间接的),因此将它们的所有名称放入全局命名空间。
据我所知,C# 没有依赖于参数的查找。ADL 与名称隐藏、重载等相结合可能会产生一些程序不受名称冲突影响的情况,而另一些则受到轻微影响,并且通过测试捕获所有极端情况是不可行的。
由于这些差异,“使用系统;” 名称冲突的可能性低于using namespace std
.
此外,命名空间“导入”在某种程度上是一种自我延续的约定:如果按照惯例导入标准命名空间,那么程序员通常会尝试避免从该命名空间中选择名称作为自己的标识符,这有助于减少与这样的约定。
如果这种导入被认为是一种不好的做法,那么程序员甚至不太可能尝试避免与导入的命名空间发生冲突。因此,即使选择之间的争论的权重最初是微妙的,惯例也会倾向于支持或反对这种做法。
推荐阅读
- terminal - 自定义 Geany 终端颜色
- python - 更新 django post_save 信号中 certail 列的值
- java - 在 JPA 中删除子项时保持实体关系同步
- .net - 将 linq 语句转换为表达式
- asp.net-mvc - 传递给控制器的值更改为 null
- compiler-errors - 如何将所有编译错误和警告从 VSCode 问题视图导出到 txt/excel 或类似文件?
- angular-material - 如何显示和隐藏特定的列?
- c# - Razor 中的选项卡只有一个选项卡处于活动状态
- python - 按日期时间过滤并根据其他数据框日期时间更新数据框
- c# - 重新抛出 AggregateException 的内部异常