为什么要在C#中删除未使用的using指令?

128

我想知道开发人员在使用Visual Studio 2008中的“删除未使用的Usings”功能时,除了整理源代码之外,是否还有其他原因?


我相信这是Visual Studio的PowerCommands功能,而不是Visual Studio本身的功能。 - Hosam Aly
3
在VS2008中,与能够对using语句进行排序一样,这肯定是VS本身的一个功能。 - Richard
1
@Hosam:PowerCommands 可以让你在整个项目/解决方案中实现这一点。每个文件单独操作是 Visual Studio 自身的一个功能。 - configurator
3
顺便说一下,如果你想更精确地控制这种清理操作,可以查看 Resharper。 - John Feminella
2
我实际上非常不喜欢这个功能 - 我总是发现自己在编辑文件后需要重新添加所有的System命名空间,因为有人已经清理了它们(通常是System、System.Collections.Generic和System.Linq)。我觉得这样做增加了更多的摩擦力而不是节省时间。现在,你自己的项目命名空间而不是框架命名空间 - 这些更有意义,可以清理,以澄清程序的连线。但希望有一种方法可以让VS仅清理某些命名空间的导入,而保留你更频繁需要的System命名空间。 - user1454265
显示剩余2条评论
10个回答

201

取出这些using语句的原因有几个。

  • 它是毫无意义的。它们没有任何价值。
  • 它容易混淆。该命名空间中使用了什么?
  • 如果不取出,随着代码变化,你将逐渐积累无用的using语句。
  • 静态分析会变慢。
  • 代码编译也会变慢。

另一方面,留下这些using语句的理由并不多。我想你可以节省删除它们的工作量。但如果你那么懒,那你就有更大的问题了!


66
一个优秀的程序员是懒惰的,他最大化地减少需要做的工作。 :D - Nicolas Dorier
41
我不认同优秀的程序员是懒惰的这种说法,但我同意你的观点。一个好的程序员会删除多余的代码,以保持代码的整洁,从而避免未来自己和他人的工作、问题或者困扰。 - Allan
3
没错,这是一个很好的链接。我想我的观点只是我们想要“好懒”,而不是“坏懒”;后者是指程序员不能被打扰地编写好的代码。 - Allan
6
在大型项目和团队中保留标准命名空间也有其优点。这样做可以减少潜在的合并冲突,并减少需要进行代码审查的文件数量。此外,许多开发人员会为某些东西添加令人困惑和难以找到的扩展方法,有时为这些扩展方法定位所需的命名空间也是一件麻烦事。新开发人员可能已经习惯了在其代码文件中包含 System.Linq,并在尝试弄清楚为什么某些方法不可用之前浪费了很多时间。 - Mark At Ramp51
6
为了避免未来编码时Intellisense变得非常愚蠢,你可能需要保留其中一些。 - yazanpro
显示剩余4条评论

26

我想说的恰恰相反 - 删除不必要的using语句非常有帮助。

想象一下,你需要在3、6、9个月后返回你的代码 - 或者其他人需要接手你的代码并进行维护。

如果你有一长串的using语句,并且其中有些其实并不需要,那么看起来可能非常令人困惑。为什么要在这里使用这个命名空间,如果从该命名空间中没有使用任何东西呢?

我想在专业环境中考虑长期可维护性时,强烈建议保持你的代码尽可能干净 - 这包括从代码中删除不必要的东西。少点混乱就意味着更高的可维护性。

Marc


18

除了已经提到的原因,它还可以防止不必要的命名冲突。请考虑这个文件:

using System.IO;
using System.Windows.Shapes;

namespace LicenseTester
{
    public static class Example
    {
        private static string temporaryPath = Path.GetTempFileName();
    }
}

这段代码无法编译,因为命名空间System.IO和System.Windows.Shapes中都包含一个名为Path的类。我们可以通过使用完整的类路径来修复它,

        private static string temporaryPath = System.IO.Path.GetTempFileName();

或者我们可以简单地删除此行using System.Windows.Shapes;


16

这对我来说似乎是一个非常明智的问题,但回答者们却以相当轻率的方式对待它。

我认为任何对源代码的更改都需要有充分的理由。这些更改可能会带来隐藏的成本,而提出这个问题的人想要了解这一点。他们并没有要求被称为“懒惰”,就像有人所暗示的那样。

我刚开始使用ReSharper,它正在对我负责的项目进行警告和样式提示。其中包括删除冗余的using指令,还有冗余的限定符、大写字母等等。我的直觉是整理代码并解决所有提示,但我的商业头脑警告我不要做出没有充分理由的更改。

我们使用自动化构建过程,因此对我们的SVN存储库进行任何更改都会生成我们无法链接到项目/错误/问题的更改,并触发自动化构建和发布,这些发布与之前版本没有任何功能上的变化。

如果我们看一下删除冗余限定符,这可能会导致开发人员混淆,因为我们域层和数据层中的类只能通过限定符来区分。

如果我看一下缩写词的正确使用(即ABCD -> Abcd),那么我必须考虑到ReSharper不会重构我们使用的引用类名的任何Xml文件。

所以,遵循这些提示并不像看起来那么简单,应该倍加尊重。

7
不错的观点,但您也不应忘记,保持清洁简洁的代码有助于提高可维护性,这也是业务目标之一。您必须权衡两者。理想情况下,您希望在发布后立即进行此类重构,以便您可以拥有尽可能干净的板块来开始新的工作,并有足够的时间来发现潜在的回归问题。 - David Reis

14

智能感知弹出窗口中的选项较少(尤其是如果命名空间包含大量扩展方法)。

理论上,智能感知应该更快。


1
+1 对于智能感知。实际上,它在启动时很慢(我经常看到“正在构建缓存,请稍后再试”),因此这可能是真正重要的。每个人都谈论的编译时间...我还没有看到具体数字。 - Luc

5

删除它们。减少代码量可以节省时间和混乱。我希望更多的人能够保持简单、整洁和有条理。这就像在你的房间里放着脏衬衫和裤子,很难看,你不得不想知道为什么会在那里。


4

最近我有另一个理由说明删除未使用的导入是相当有帮助和重要的。

想象一下你有两个程序集,其中一个引用了另一个(现在我们称第一个为A,被引用的为B)。当你在A中有依赖于B的代码时,一切都很好。然而,在开发过程中的某个阶段,你注意到实际上不再需要那段代码,但是你保留了原来的using语句。现在你不仅拥有无意义的using指令,还拥有一个程序集引用B,该引用在已经废弃的指令中没有任何用处。首先,这增加了编译A所需的时间,因为也必须加载B

因此,这不仅是一个更清洁、易读的代码问题,还是一个在生产代码中维护程序集引用的问题,其中并非所有这些被引用的程序集甚至不存在

最后,在我们的示例中,我们必须将B和A一起发布,尽管B在A中除了在using部分没有任何用途。这将严重影响A运行时性能,尤其是在加载程序集时。


4
代码编译更快速。

5
你有任何证据来支持那个说法吗? - cjk
16
哦,CK - 你再次抓住了我。我撒谎了。去除不必要的文本实际上会使代码编译得更慢。想一想 :) - Dead account
19
希望能看到一些真实的统计数据。如果我们在编译时仅节省了几毫秒,那么速度并不是一个有说服力的论点。然而,除了速度之外,还有其他理由需要去除不必要的using语句。 - Greg
3
重点不在于撒谎与否。任何明智的人都会猜测,减少杂乱意味着更高效。支持这一观点的"证据"是提供价值来回应,并支持"更快"并不仅仅是几毫秒,而是为更快地编译项目带来改进体验的论点。 - Matheus Felipe
1
事实上,我会为类、变量和方法编写简短的名称,以便编译更快的代码。当我花费1分钟去查找使用System.Linq时缺失的内容,当我尝试使用First/FirstDefault/Single/Single/FirstOrEmpty/SingleOrSomething/DefaultWhenNull...时,“WTF...我确定有一个方法可以做到这一点...为什么我找不到它?”或者“为什么Int32今天不能编译?”我认为失去的1分钟比编译中获得的1/1000秒更糟糕。 - Alex 75

3
它还有助于防止虚假的循环依赖,假设您在删除未使用的 using 后也能从项目中删除一些 dll/project 引用。

2
至少在理论上,如果你拿到了一个C# .cs文件(或者任何单个程序源代码文件),你应该能够查看代码并创建一个模拟它所需的一切的环境。通过一些编译/解析技术,你甚至可以创建一个自动执行此操作的工具。如果你至少在心中这样做,你可以确保你理解代码文件所说的一切。
现在考虑一下,如果你拿到了一个有1000个using指令的.cs文件,而其中只有10个被实际使用。每当你查看引用外部世界的新引入的符号时,你都必须浏览这1000行才能弄清楚它是什么。这显然会减慢上述过程的速度。因此,如果你能将它们减少到10个,这将有所帮助!
在我看来,C#的using指令非常非常弱,因为你无法指定单个泛型符号而不失去泛型性,并且你不能使用using别名指令来使用扩展方法。但在其他语言(如Java、Python和Haskell)中则不是这种情况,在这些语言中,你能够(几乎)精确地指定你想要从外部世界获取的内容。但即便如此,我仍建议尽可能使用using别名。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接