【问题标题】:Why is this name with an underscore not CLS Compliant?为什么这个带下划线的名称不符合 CLS 标准?
【发布时间】:2009-07-28 15:49:58
【问题描述】:

为什么会收到编译器警告

标识符“Logic.DomainObjectBase._isNew”不符合 CLS

下面的代码?

public abstract class DomainObjectBase
{
    protected bool _isNew;
}

【问题讨论】:

  • 你可能不应该用下划线标记非私人成员。我知道每个人都有自己的风格,但其他人几乎肯定会认为该领域是不符合惯例的私有领域。
  • @EdS。哪个约定?
  • 似乎曾经是一种 VB 约定,对于 C++、C# 来说,它似乎也过时了,更多详细信息无法在此框中找到:stackoverflow.com/questions/3136594/…
  • @Pharap:使用前导下划线命名私有成员是很常见的。我相信fieldName 在 C# 中更常见(至少,这是我经常看到的),但有些人不喜欢它,包括我自己,因为它迫使你到处写 this.
  • @Pharap:实际上,他们没有:msdn.microsoft.com/en-us/library/ms229012(v=vs.110).aspx“指南未涵盖内部和私有字段”。你指的是 static 成员,完全不同的野兽。此外,在 C++ 中使用 single 前导下划线作为私有标识符后跟小写字母并没有错。全局命名空间中的任何内容或后跟大写字母,是的。

标签: c# .net cls-compliant


【解决方案1】:

来自Common Language Specification

符合 CLS 的语言编译器必须遵循 Unicode 标准 3.0 技术报告 15 附件 7 的规则,该规则管理可以开始并包含在标识符中的字符集。该标准可从 Unicode 联盟的网站获得。

如果你look this up:

也就是说,标识符的第一个字符可以是大写字母、小写字母、首字母大写字母、修饰字母、其他字母或字母数字。标识符的后续字符可以是这些字符中的任何一个,加上非间距标记、间距组合标记、十进制数字、连接符标点和格式代码(例如左右标记)。通常在存储或比较标识符之前应该过滤掉格式化代码。

基本上,您不能以下划线开头标识符 - 这违反了在可见(公共/受保护)字段上的 CLS 合规性。

【讨论】:

  • 什么是“字母编号”?
  • @Kevin:上面 sn-p 中的所有术语都指的是 Unicode 类别:“字母,大写”,“字母,小写”,“字母,标题大小写”,“字母,修饰符”, “字母,其他”和“数字,字母”。罗马数字是“字母数字”的一个例子。见fileformat.info/info/unicode/category/Nl/list.htm
【解决方案2】:

CLS compliance 与不同.NET 语言之间的互操作性有关。该属性不符合 CLS,因为它以下划线开头并且是公共的(注意:公共类中的受保护属性可以从程序集外部访问)。虽然如果从 C# 访问该属性这将起作用,但如果从其他不允许在属性名称开头使用下划线的 .NET 语言访问它可能不会,因此它不符合 CLS。

您收到此编译器错误,因为您在代码中的某处将您的程序集标记为符合 CLS,如下所示:

[assembly: CLSCompliant(true)]

Visual Studio 将这一行包含在 AssemblyInfo.cs 文件中,该文件可以在大多数项目的“属性”下找到。

要解决此错误,您可以:

  1. 重命名您的资源(推荐):

    protected bool isNew;
    
  2. 将您的整个程序集设置为不符合 CLS:

    [assembly: CLSCompliant(false)]
    
  3. 为您的属性添加一个属性:

    [CLSCompliant(false)]  
    protected bool _isNew;
    
  4. 更改属性的范围,使其在程序集之外无法看到。

    private bool _isNew;
    

【讨论】:

  • 那么,当你有一个带有受保护变量的公共属性时,最好的约定是什么?
  • 我个人喜欢将所有字段设为私有。如果我需要增加范围,我会将其包装在 Property Get/Set 中。
  • @MartinBrown:在许多情况下,类将具有公共属性,其设置器调用处理更新的受保护方法,但派生类型可能有合法需要直接使用该字段并发布更新之后(例如,如果从控件派生的类具有更改其颜色和标题的方法,但基类没有,则派生类更改这两个字段然后调用一次更新方法可能会有所帮助)。我倾向于使用“Characteristic”和“_characteristic”,因为 VB.NET 和 C# 都接受它。你有什么建议?
  • @supercat:在我 13 年的 .Net 全职编程生涯中,我想我不记得曾经需要这样做。但如果我这样做了,我会选择不带下划线的 camelCase 字段名称。
  • @MartinBrown:与属性名称匹配的字段名称(大小写除外)不仅符合 CLS,而且会使标识符在 VB.NET 中不可用。
【解决方案3】:

前导 underscore 伴随 _isNew 可见(即不私有)。

【讨论】:

  • +1 但您需要包含成员非私有这一事实,这与前导下划线一起使成员的名称不符合 CLS。跨度>
【解决方案4】:

下划线会导致问题。通常的做法是下划线保留给私有字段。受保护/公共成员应正确区分大小写和命名。

例如:

public abstract class DomainObjectBase{   
   private bool _isNew;
   protected bool IsNew { get { return _isNew; } set { _isNew = value;} }
}

或者,如果您想使用 3.x 并摆脱私有字段:

public abstract class DomainObjectBase{   
   protected bool IsNew { get; set; }
}

【讨论】:

    【解决方案5】:

    符合 CLS 的标识符不应以下划线开头。

    【讨论】:

      【解决方案6】:

      是下划线。看到这个article

      【讨论】:

        【解决方案7】:

        前导 _ 不符合 CLS

        Microsoft StyleCop 将分析您的代码,并提供指向相关文档的链接,解释为什么它不符合 CLS。

        【讨论】:

        • 我喜欢 StyleCop 的想法,但它的规则与 FxCop 规则、Resharper 的重新格式化程序和 Visual Studio 重新格式化程序有冲突。
        • StyleCop 和 FxCop 均由 Microsoft 生产(尽管由不同的产品团队生产),但我相信 StyleCop 是后者,因此如果您希望使用“Microsoft”代码样式,则更首选。
        【解决方案8】:

        因为数据成员的名称 _isNew 以下划线开头。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2010-09-05
          • 2014-06-28
          • 1970-01-01
          • 1970-01-01
          • 2017-07-28
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多