Visual Studio在不必要时建议使用完全限定的命名空间

15

使用Visual Studio 2010(可能也包括2008),我注意到Intellisense将为枚举类型建议完全限定的命名空间。

例如,我可以编写如下代码:

element.HorizontalAlignment = HorizontalAlignment.Right;
element.VerticalAlignment = VerticalAlignment.Bottom;

但是当我尝试写它时,它建议我像这样写:

element.HorizontalAlignment = System.Windows.HorizontalAlignment.Right;
element.VerticalAlignment = System.Windows.VerticalAlignment.Bottom;

这些不必要的额外代码可能会累积起来,使代码难以阅读,我必须与Intellisense斗争才能避免它。

有什么原因吗?我能关掉它吗?我猜原因是枚举的名称与属性的名称相同。但这真的不是一个好的理由。

编辑:

这里是另一个示例,说明完全限定名称并非必需。

using SomeOtherNamespace;

namespace SomeNamespace
{
    public class Class1
    {
        public Class2 Class2 { get; set; }

        public Class1()
        {
            // These all compile fine and none require fully qualified naming.  The usage is context specific.
            // Intellisense lists static and instance members and you choose what you wanted from the list.

            Class2 = Class2.Default;
            Class2.Name = "Name";
            Class2.Name = Class2.Default.Name;
            Class2 = Class2;
        }
    }
}

namespace SomeOtherNamespace
{
    public class Class2
    {
        public static Class2 Default { get; set; }

        // public static Class2 Class2;  (This throws an error as it would create ambiguity and require fully qualified names.)

        // public static string Name { get; set; }  (This also throws an error because it would create ambiguity and require fully qualified names.

        public string Name { get; set; }
    }
}

有趣的是,就我所记得的,当不需要时,VS从未建议完全限定名称。 - Andrew Barber
我之前在一个Windows Forms应用程序中遇到了同样的问题。它建议我写System.Windows.Forms.DialogResult.OK而不是仅仅DialogResult.OK。再次说明,我相当确定这是因为在该范围(一个窗体)中有一个名为“DialogResult”的本地属性。 - Trevor Elliott
在这种情况下,我认为这是必需的。 - Andrew Barber
这并不是必需的,因为上下文已经明确了,就像你可以创建一个名为“public Image Image”的属性一样。写成“DialogResult = DialogResult.OK”是可以编译通过的,因为没有歧义。将其写成“DialogResult = System.Windows.Forms.DialogResult.OK”是不必要的。 - Trevor Elliott
Visual Studio 11有同样的“功能”。 - Trevor Elliott
显示剩余4条评论
5个回答

6

我没有System.Windows.Forms的引用。 - Trevor Elliott
@Moozhe:是否有任何Office的dll文件? - Tigran
@Moozhe:没错,但我不知道提供的代码是否可编译,这就是我为什么会有那样的疑问。 - Tigran
我已经有了 "using System.Windows"。我没有出现错误,我得到的是一个坏的和讨厌的建议。 - Trevor Elliott
建议(suggestion)就是关于保持完全限定名称的意义,只是因为这样做是一种良好的实践而已,没有其他意思。 - Tigran
显示剩余7条评论

5

这似乎是属性和类型的相同名称。
以下是最小的可重现示例,模拟了这个问题(可以更小,但这会暴露更多的信息)...

namespace Company.Project.SubProject.Area.Test.AndSomeMore
{
    public class TestClass
    {
        public TestEnum MyEnum { get; set; }
        public TestEnum TestEnum { get; set; }
        public SndTestEnum NewEnum { get; set; }
    }
    public enum TestEnum
    {
        None,
        One,
        Two
    }
    public enum SndTestEnum
    {
        None,
        One,
        Two
    }
}
namespace MyCallerNS
{
    public class MyTestClass : TestClass
    {
        public MyTestClass()
        {
            this.TestEnum = Company.Project.SubProject.Area.Test.AndSomeMore.TestEnum.One;
            this.MyEnum = Company.Project.SubProject.Area.Test.AndSomeMore.TestEnum.Two;
            this.NewEnum = SndTestEnum.None;
        }
    }
}

MyEnumTestEnum属性(针对TestEnum枚举)都提供“完全限定名”(其中一个名称与其属性类型不同,但该类型与另一个属性的名称相匹配,因此两者均“污染了”)-而SndTestEnum具有不同的命名(对于类型、属性),在任何情况下都可以正常工作。

...有趣的是,即使您删除namespace MyCallerNS并将所有内容放在“长名称空间”下,它仍将在前面添加AndSomeMore.

就我所看到的(除了Re#和第三方工具之外),没有解决方案, 这似乎是 IntelliSense 没有编译器那么聪明的原因,如@Rick所建议的。

或者更确切地说,编译器花费时间去解析事物(拥有所有信息),而 IntelliSense 没有那种“深度”和洞察力(我猜测,简化实际上-我们需要@Eric来解释 :) 并快速/最简单地作出选择。

实际上,在我之前的想法中, 更多关于每个执行的“工作”,IntelliSense(作为完成“服务”)必须向列表中呈现所有选项(属性名称和类型)(我没有看到它们都存在,但猜测。而且只有一个选择来覆盖两个可能很麻烦), 因此为了区分它添加了完全限定名。
在它“失败”的地方(有点),是将“短版本”“粘贴”在末尾-我认为它确实应该这样做。


2

我发现如果我输入element.HorizontalAlignment =,那么VS2010会自动建议System.Windows.HorizontalAlignment,如果您按下tab键,则会选中该建议。如果您输入“Ho”来缩小列表,而不是按tab键,然后再按tab键,您将只得到HorizontalAlignment。

如果您能够使用Resharper,则在输入“=”后,您将会看到最明显的选择:

HorizontalAlignment.Center
HorizontalAlignment.Left
HorizontalAlignment.Stretch
HorizontalAlignment.Right

这很可能是正确的答案。我实际上研究了这个问题,并发现其他人说Resharper没有解决这个问题,但那可能是旧版本或错误信息。我今晚会尝试一下。 - Trevor Elliott
我正在使用 R# 6.1 和 7。我记不得以前的版本行为是什么了。 - Phil
我试用了R# 6.1和7。有趣的是,它会破坏默认的Intellisense预选功能。在Resharper选项->环境->Intellisense->Autopopup->C#下,它提到了Preselecting作为一个选项,但它并没有预选,事实上,即使你选择“显示而不是预选”,行为似乎也完全相同。 - Trevor Elliott
不预先选择,您需要移动手到鼠标点击,或者将手移动到箭头键。对于枚举,我习惯不必将手离开主键盘区域。例如,键入HorizontalAlignment = HorizontalAlignment.Center应该只需2个按键即可选择,而无需离开主键盘位置。您只需要键入一个句号,然后是“C”。 - Trevor Elliott
是的,同意。R# 在枚举内部不考虑句号确实很烦人。但是你可以使用驼峰式智能感知。例如,输入“= HAC”或“= HAT”。 - Phil

1

这是编译器比Intellisense更聪明的情况。

如果您正在访问与其类型相同名称的属性,例如“public TextAlignment TextAlignment { get; set; }”,则无需完全限定枚举值被分配给它的命名空间。但是,Intellisense似乎不够聪明,不知道这一点。代码将在没有资格的情况下正常工作,您只需要注意并避开Intellisense即可。


你是说Visual Studio 2005中的Intellisense比VS 11中的更智能吗?我在工作中使用的是VS2005,我从未遇到过这个问题,一次都没有。 - Trevor Elliott
我不知道?自2008年以来,我就没有使用过2005。 - Rick Brewster

0
除了上面的答案之外,我还参与了一些涉及到 Microsoft Office 自动化的项目。我的课程结构如下:
  • CustomNameSpace.Library.Microsoft.Word.CustomClass1
  • CustomNameSpace.Library.Microsoft.Excel.AnotherCustomClass

当试图访问.NET框架中的Microsoft命名空间内的任何内容时,Intellisense会强制您完全限定名称。在根冲突的情况下,它还将前置全局关键字,如下所示:global::Windows.Forms.etc...


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