为什么C#"使用别名"默认情况下不使用?

时间:2017-04-13 03:47:41

标签: c# .net visual-studio ide

请考虑以下代码。

using System.ComponentModel.DataAnnotations;

namespace Foo
{
    public class Bar
    {
        [Required, MaxLength(250)]
        public virtual string Name { get; set; }
    }
}

除非你有一个花哨的IDE(即在幕后进行各种查找和静态分析),否则它在哪里"必需" &安培; "的MaxLength"实际上来自。特别是当可能导入多个名称空间时,具有相似的含义。

作为C#的相对新手,我发现自己总是很难搞清楚某些事情的来源。特别是在查看StackOverflow等地方的其他代码片段时。

using DataAnnotations = System.ComponentModel.DataAnnotations;

namespace Foo
{
    public class Bar
    {
        [DataAnnotations.Required, DataAnnotations.MaxLength(250)]
        public virtual string Name { get; set; }
    }
}

现在,非常明显的地方"必需" &安培; "的MaxLength"来自。您可以采取另一个步骤,并执行以下操作:

using Required = System.ComponentModel.DataAnnotations.RequiredAttribute;
using MaxLength = System.ComponentModel.DataAnnotations.MaxLengthAttribute;

namespace Foo
{
    public class Bar
    {
        [Required, MaxLength(250)]
        public virtual string Name { get; set; }
    }
}

现在非常类似于PHP& Js ES6有效。

我很好奇为什么这不是C#的默认值?为什么我和其他所有C#开发人员一起考虑别名的不良做法?是否存在一些潜在的性能原因?

1 个答案:

答案 0 :(得分:7)

为什么类型/定义来自何处?

如果您真正关心类型所在的命名空间,Visual Studio能够以几种方式查找,我最喜欢的两种方式如下:< / p>

  • 将鼠标悬停在类型/声明中。这通常会显示完整的类型名称。 (悬停new SomeType()语句会显示方法名称,即应用于属性的方法名称。)
  • 按F12 /转到定义。即使您没有定义来源,也可以使用 F12 右键单击 - &gt; 转到定义会将您带到显示该类型的所有公共成员的元数据文件。这不适用于关键字(outrefreturnnull等),但它适用于基本别名类型(intstring等)和传统类型(enuminterfaceclassstruct等)。这包括命名空间,类型名称和所有公共API成员。如果有XML文档,也包含它们。如果 F12 是一个扩展方法,它会将您带到该扩展方法的类元数据。如果您觉得它是由不应该的东西注入的话,那么非常有助于识别方法的来源。

所以现在它不是真的那么难以确定该类型来自哪个命名空间。那么using别名呢,我们实际什么时候需要它们?

真实场景:我一直致力于XNA Framework的Windows窗体模型。 XNA Framework具有Color类型,我的框架具有Color类型。现在我经常将这两个命名空间一起使用,但只需要本地使用的{em>一个 Color类型。我经常会有using语句列表,其中包含以下内容:

using XnaColor = Microsoft.Xna.Framework.Color;
using Color = Evbpc.Framework.Drawing.Color;

因此,这解决了歧义问题。

为什么没有using别名为默认值?

可能是因为他们几乎从不必要。我们不会真的需要它们。如果您关注某个类型的命名空间,那么更容易进行快速查找,而不是别名所有内容和强制命名空间被定义为。按照这个速度,您可以完全禁止using语句并完全限定所有内容。

对于using别名,我曾经曾经的最大两个用例是:

  1. 解决类型之间的歧义。请参阅上面的示例。
  2. 解决命名空间之间的歧义。与上面的想法相同,但如果复制了很多类型,我会将整个命名空间别名。

    using XnaF = Microsoft.Xna.Framework;
    using Evbpc.Framework.Drawing;
    
  3. 如果您使用Visual Studio生成代码,导入类型等,则 将使用别名。相反,Visual Studio将根据需要对名称进行完全限定。是否右键单击了一个波形,并将A.B.Type作为唯一选项,而不是using A.B嗯,这通常是别名的好地方。

    我会警告你,using别名似乎会增加可维护性要求。 (这可能没有备份数字,但我不会说谎 - 这个我有几个别名的项目会让我忘记我经常命名别名的方式。)

    通常,根据我的经验,如果您必须使用using别名,则可能在某处违反规则。

    为什么我们甚至定期使用它们?

    因为他们很糟糕。他们让代码更难阅读(以DataAnnotations.MaxLength为例,为什么我需要阅读?我不在乎MaxLengthSystem.ComponentModel.DataAnnotations,我只关心它已正确设置),它们会破坏代码(现在我强制要记住属性在System.ComponentModel.DataAnnotations而不是System.ComponentModel.DataAnnotations.Schema),而且它们通常只是笨重。

    采用前面的示例,我有一个Entity Framework项目,该项目在类上具有类似以下的属性:

    using System.ComponentModel.DataAnnotations;
    using System.ComponentModel.DataAnnotations.Schema;
    
    [Key, Column(Order = 2)]
    [MaxLength(128)]
    public string UserId { get; set; }
    
    [ForeignKey(nameof(UserId))]
    public virtual ApplicationUser User { get; set; }
    

    现在以您的示例为例,我将拥有以下其中一项:

    using DataAnnotations = System.ComponentModel.DataAnnotations;
    
    [DataAnnotations.Key, DataAnnotations.Schema.Column(Order = 2)]
    [DataAnnotations.MaxLength(128)]
    public string UserId { get; set; }
    
    [DataAnnotations.Schema.ForeignKey(nameof(UserId))]
    public virtual ApplicationUser User { get; set; }
    

    或者:

    using DataAnnotations = System.ComponentModel.DataAnnotations;
    using Schema = System.ComponentModel.DataAnnotations.Schema;
    
    [DataAnnotations.Key, Schema.Column(Order = 2)]
    [DataAnnotations.MaxLength(128)]
    public string UserId { get; set; }
    
    [Schema.ForeignKey(nameof(UserId))]
    public virtual ApplicationUser User { get; set; }
    

    或者更糟糕的是:

    using KeyAttribute = System.ComponentModel.DataAnnotations.KeyAttribute;
    using MaxLengthAttribute = System.ComponentModel.DataAnnotations.MaxLengthAttribute;
    using ColumnAttribute = System.ComponentModel.DataAnnotations.Schema.ColumnAttribute;
    using ForeignKeyAttribute = System.ComponentModel.DataAnnotations.Schema.ForeignKeyAttribute;
    
    [Key, Column(Order = 2)]
    [MaxLength(128)]
    public string UserId { get; set; }
    
    [ForeignKey(nameof(UserId))]
    public virtual ApplicationUser User { get; set; }
    

    对不起,但那些只是可怕的。这就是为什么每一个&#39;你说话的开发人员避开它们并认为这是一个坏主意。我只是坚持智能 [1] 导入命名空间并处理类型冲突的非常小的潜力。 然后我会使用别名。

    如果确实无法找到类型所在的命名空间(例如从Stack Overflow中提取代码),请点击MSDN,转到Library并搜索类型。 (即,搜索KeyAttributeMaxLengthAttribute,第一个链接是API引用。)

    [1]:聪明地 我的意思是责任和关怀。不要盲目地导入/使用命名空间,尽可能地限制它们。 SRP和多​​态通常允许我们在每个文件中保持using列表非常小。