【问题标题】:How do I disable the implicit "this" in C#?如何禁用 C# 中的隐式“this”?
【发布时间】:2010-10-31 18:16:54
【问题描述】:

这让我很困扰,我发现与 Intellisense (VS 2008 Pro) 结合使用时会写出愚蠢的错误:

class Foo
{
    public Foo(bool isAction)
    {
        this.IsAction = IsAction;
    }

    public bool IsAction { get; private set; }
}

你抓到了吗?我当然没有,直到 IsAction 从未改变,导致错误。

Intellisense 以某种方式将“isA<tab>”转换为“IsAction”,这意味着无论构造函数输入如何,Foo.IsAction 属性总是为假。简直太棒了。

我不得不说我特别讨厌“隐式this”(我不知道它是否有正式名称)并且我想将其关闭,因此它永远不会假设它。 有没有办法做到这一点? 这也适用于调用同一类的静态方法。

或者,什么命名约定可以避免这个小问题? 属性必须保持为“IsAction”,因此它必须是构造函数参数名称的约定。奇怪的是,如果我用完全匹配的拼写命名它,那么 this.IsAction = IsAction; 会正确运行。

问题不在于区分大小写的语言,而是this 的隐含性。现在我想起来了,这也更像是一个 VS 2008 Pro 的问题,而不是 C#。我可以忍受没有this 的已经编写的代码,但我不想在没有它的情况下编写新代码,这意味着告诉 In


诺多林的回答让我思考。

现在我想起来了,这更像是 VS 2008 的问题,而不是 C#。我可以在没有this 的情况下使用已经编写的代码(尽管如果我在那里乱七八糟,我会更改它)但我不想在没有它的情况下编写新代码,这意味着告诉 Intellisense 停止这样做。 我可以告诉 Intellisense 关闭它吗?

【问题讨论】:

  • 这不是隐含的问题。即使你可以关闭它(我认为你不能),我相信你会在几分钟内再次打开它。
  • 我很确定我不会。我有提到我讨厌吗? :)
  • 我很想看看你的代码没有它,每次调用私有或受保护的方法都以“this”开头......好的类包含许多小的重构和表达方法来实现它们的目标。你会到处都是“这个”。
  • 对不起,我是一个新手程序员,但据我所知,您的代码没有任何问题,只是您传递的变量和您分配的变量不同。区分大小写是我在这里看到的恶魔。

标签: c# visual-studio-2008 .net-3.5 this


【解决方案1】:

我刚刚在 Visual Studio 2008 中尝试过您的代码。打开内置静态分析会产生以下错误:

警告 3 CA1801:Microsoft.Usage: 参数“isAction”的 'Foo.Foo(bool)' 从未使用过。消除 参数或在方法中使用它 身体。

我的建议是打开此功能,您会尽早发现此类错误。要启用此功能,请从项目的上下文菜单中选择属性,然后选择代码分析选项卡并选择“在构建时启用代码分析”

【讨论】:

    【解决方案2】:

    你总是可以回到匈牙利符号[我正准备在我输入这个时被激怒]。如果你能处理丑陋,它会解决你的问题。这是一个建议,不是推荐。

    另外,我非常确定静态代码分析会捕捉到这一点并警告您。试试 FxCop。

    编辑

    我已经使用 Resharper 一年多了,我知道以区分大小写的方式帮助您非常聪明。除其他好处外,您的智能感知问题将通过安装 Resharper 得到解决。

    编辑 2

    我刚刚检查过。 FxCop 和 Resharper 都没有直接捕捉到这个错误。两者都抓住了 isAction 参数在 Foo 方法中未使用的事实。在这种情况下,警告会提示您错误。如果参数在方法中以其他方式使用,它可能会通过静态代码分析。

    【讨论】:

    • 我知道他提到匈牙利表示法(尽管我不推荐它)会引起反对。 :)
    • 是的,但是静态代码分析的建议得到了我的 +1 ......它会抓住这个 :-)
    • 请不要使用匈牙利符号!如果您不推荐它,我不确定您为什么会提到它。
    • Systems Hungarian(您在变量名称中表示“count”或“index”而不是“int”或“long” - 请参阅msdn.microsoft.com/en-us/library/aa260976(VS.60).aspx)对我来说似乎非常有用,如果它帮助你更好地控制环境,那为什么不呢? (我不得不说使用 Apps Hungarian 的想法让我很恼火——这样的冗余真的让我毛骨悚然。)
    • StyleCop 应该抓住这个 - 如果你愿意忍受它!
    【解决方案3】:

    这是一个常见问题。 Microsoft 有一些 recommendations for parameter names,但它们对您的情况并没有太大帮助。

    正如其他响应者所提到的,您不能“禁用”C# 语言范围解析行为 - 您最好的方法是命名约定。其他人提到了“匈牙利”符号 - 由于符号的confusion over the original intent,有些人对此有下意识的反应。

    我个人的做法是使用字符“p”作为公共函数的参数名称的前缀。它不显眼、简单、易于识别,并且易于使用Resharper 等工具实施。

    您选择的特定命名约定取决于偏好和风格;但是,在您选择的实践中保持一致会带来一些好处。

    使用我建议的命名约定,您可以将构造函数编写为:

    class Foo
    {
        public Foo(bool pIsAction)
        {
            this.IsAction = pIsAction;
        }
    
        public bool IsAction { get; private set; }
    }
    

    【讨论】:

    • 参数名称是接口的一部分,对调用者可见。您可能会发现成员字段的约定会更好。
    【解决方案4】:

    FxCop 会抱怨这一点,因为从未使用过 isAction 参数。具体来说,它将拉取规则 CA1801:ReviewUnusedParameters。

    我个人一直认为 C# 编译器应该对未使用的参数发出警告。

    【讨论】:

      【解决方案5】:

      这一直困扰着我。我已经开始使用'_'在传递给构造函数的变量之前添加,例如:

      class Foo
      {    
          public Foo(bool _isAction)
          {
              this.IsAction = _isAction;
          }
          public bool IsAction { get; private set; }}
      

      【讨论】:

      • 通常,下划线保留用于指示实例变量,而不是参数。使用它来指示参数应该没问题,但对于不熟悉您的约定的开发人员来说可能会令人沮丧。
      • 如果我不执行自动属性,那么我将我的属性命名为“IsAction”,并将我的支持字段命名为“_IsAction”,这样该约定将不适用于这些。 :)
      • 我以前也看到过,但它非常丑陋。命名私有字段(有时甚至被 Microsoft 使用)是一种可以接受的做法,但对于参数肯定不行。
      • 我也不喜欢它,但是当前的公司编码标准禁止在其他任何地方使用“_”,所以它有点工作。关键是要获取与属性名不同的参数名。
      • 这个解决方案的问题是你根本看不到 BCL 中的方法中带有下划线的参数,这使得你的风格与其他人不一致。
      【解决方案6】:

      恐怕无法禁用“隐式this”功能。它是语言规范和编译器的一部分,没有办法将其关闭。

      就个人而言,我不认为这是一个大问题。诚然,注意成员和参数名称的大小写很重要,但在 C# 等区分大小写的语言中总是如此。

      我推荐的“解决方案”(您似乎已经这样做了)是始终使用 this 关键字来引用属性/字段,以便在您应该使用参数时立即脱颖而出。它不会为您解决问题,但如果您牢记这一点,它无疑会有所帮助。只要养成这样的习惯(以及记住所有参数/局部变量的名称都应该以小写开头)将有助于您在以后避免这个问题。

      【讨论】:

      • 我本来打算发表评论,但我会马上修改我的问题。
      • 据我所知,您想禁用所有 properties 的智能感知建议吗?我很确定这是不可能的,但我会考虑一下。
      • 我希望它不引入隐式类成员,即实例,但静态也可以。
      • @Colin:是的,我想我知道你从哪里来了。问题归结为 C# 区分大小写但 VS Intellisense 。在我看来,Intellisense 确实应该区分大小写,至少在第一个字符上是这样。但是,我想不出一个好的解决方案。您可以简单地禁用 Intellisense 完成列表吗?
      【解决方案7】:

      这是 Visual Studio 智能感知中的一个恼人问题。 Resharper 大部分时间都是正确的。

      【讨论】:

        【解决方案8】:

        我认为开发人员更有可能从 Intellisense 中选择“IsAction”而不是“isAction”。我认为 Intellisense 不会将“isA”更改为“this.IsAction”。

        如果名称只是大小写不同,那么我认为防止此类错误的唯一方法是了解它们并小心谨慎,并有效地使用单元测试。

        【讨论】:

        • 是的,因为在这种情况下,它会默认使用默认 VS 智能感知中更具体的大小写匹配(即 isAction 参数)。这是用户错误 ;-)
        • 如果你认真对待它,那么 bug 来自开发人员错误。说开发人员错误导致了错误是多余的,对我的问题毫无帮助。我正在寻找一种方法来减少这些错误以避免错误。
        • 这将在 C# 中工作;)。而且,属性应该总是以大写字母开头(即使代码分析也会告诉你,如果我是对的)。代码中的函数也是如此......它应该始终以大写字母开头。
        • @Colin - 请参阅我的回答中的第二句话。如果名称仅因大小写而异,那么 Intellisense 无法防止错误发生。一个好的单元测试会抓住它。
        • @Jamie Ide,在某种程度上,这是最终的解决方案,不是吗?遵守 TDD 原则意味着您首先将其编写失败,然后再实现该功能。首先看到它失败将确保您知道何时停止(何时成功),因此您永远不会假设它在没有验证的情况下工作。
        【解决方案9】:

        在其他功能中可能会很烦人,但您可以关闭让 Intellisense 预先选择最近使用的成员的选项。我意识到这并不能真正彻底解决问题,但当您没有真正选择正确的项目时,它可能有助于防止出现一些意外选项卡。

        【讨论】:

          【解决方案10】:

          注意:

          如果您使用的是 Resharper,您可以使用一些快捷方式为您编写大量此类代码并避免错误。

          您可以先创建属性,然后按 Alt-Ins 并选择“生成构造函数”,也可以向构造函数添加参数“isAction”,在 parameterName 中使用插入符号按 Alt-Enter,然后选择从弹出的菜单中“创建和初始化 Auto-property IsAction”操作。

          【讨论】:

          • 我最喜欢的另一个是成员的名字很长。我使用智能感知通过键入 IAATIVL 来查找 IsAnotherActionThatIsVeryLong,并通过键入 iAATIVL 来查找 isAnotherActionThatIsVeryLong。在拥有它之前,我从不知道自己错过了它。
          【解决方案11】:

          自 2009 年提交这些其他答案以来,情况发生了变化。我看到这个问题被标记为 visual-studio-2008 但这可能仍然对某人有所帮助。在 Visual Studio 的最新版本(例如 Visual Studio 2019)中,可以将 IDE 配置为检查 C# 代码的代码样式一致性。可用的检查之一是要求显式使用 this

          转到选项 > 文本编辑器 > C# > 代码样式 > 常规,您将在其中找到一个名为 'this.' 的组。偏好。将每个设置为 Prefer 'this.' 并将 Severity 设置为 Error

          C# 代码中的任何违规都将导致代码样式检查错误显示在 IDE 中。不过奇怪的是,这不会导致构建失败。

          另请参阅documentation on the EditorConfig file format,其中相关参数的名称类似于dotnet_style_qualification_for_field

          【讨论】:

            【解决方案12】:

            进一步的想法是:

            1. 实现您自己的检查器,例如通过搜索正则表达式\b(\w+)\b\s*=\s*\1。这将找到所有自赋值,而不仅仅是在类构造函数中。它在理论上不是万无一失的(例如,它不会捕获带有/**/ 评论的自我分配),但它应该在所有实际场景中都足够好。

            2. 如果你不介意额外的输入,你可以先给构造函数参数一个不同的名字,然后在编写构造函数的主体之后重命名它。

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2020-04-09
              • 1970-01-01
              • 2014-08-10
              • 1970-01-01
              • 1970-01-01
              • 2015-06-08
              • 2011-08-15
              • 2018-04-30
              相关资源
              最近更新 更多