c# - 为什么我可以声明一个与父作用域中的变量同名的子变量?

标签 c# lambda scope c#-8.0 variable-names

我最近写了一些代码,我无意中将一个变量名重用作为一个 Action 的参数,该 Action 在一个已经具有同名变量的函数中声明。例如:

var x = 1;
Action<int> myAction = (x) => { Console.WriteLine(x); };

当我发现重复时,我惊讶地发现代码编译并完美运行,根据我对 C# 中作用域的了解,这不是我所期望的行为。一些快速的谷歌搜索出现了提示类似代码确实会产生错误的 SO 问题,例如 Lambda Scope Clarification . (我将该示例代码粘贴到我的 IDE 中以查看它是否可以运行,只是为了确保它运行完美。)此外,当我在 Visual Studio 中进入“重命名”对话框时,第一个 x突出显示为名称冲突。

为什么这段代码有效?我在 Visual Studio 2019 中使用 C# 8。

最佳答案

Why does this code work? I'm using C# 8 with Visual Studio 2019.



你已经回答了你自己的问题!这是因为您使用的是 C# 8。

C# 1 到 7 的规则是:一个简单的名称不能用于表示同一本地范围内的两个不同的事物。 (实际规则比那稍微复杂一些,但描述如何是乏味的;有关详细信息,请参阅 C# 规范。)

此规则的目的是防止您在示例中谈论的那种情况,在这种情况下,很容易混淆本地的含义。特别是,此规则旨在防止混淆,例如:
class C 
{
  int x;
  void M()
  {
    x = 123;
    if (whatever)
    {
      int x = 356;
      ...

现在我们的情况是在 M 的主体内部。 , x表示两者 this.x和本地 x .

尽管本意是善意的,但这条规则存在许多问题:
  • 它没有实现规范。在某些情况下,一个简单的名称可以同时用作类型和属性,但这些并不总是被标记为错误,因为错误检测逻辑存在缺陷。 (见下文)
  • 错误消息措辞困惑,报告不一致。这种情况有多种不同的错误消息。他们不一致地确定了罪犯;也就是说,有时会调用内部用法,有时会调用外部用法,有时只是混淆。

  • 我在 Roslyn 重写中努力解决这个问题;我添加了一些新的错误消息,并使旧的消息与报告错误的位置保持一致。然而,这种努力来得太少,也太迟了。

    C# 团队决定在 C# 8 中整条规则造成的困惑多于防止的困惑,并且该规则从语言中退休。 (感谢 Jonathon Chase 确定何时退休。)

    如果您有兴趣了解这个问题的历史以及我如何尝试修复它,请参阅我写的这些文章:

    https://ericlippert.com/2009/11/02/simple-names-are-not-so-simple/

    https://ericlippert.com/2009/11/05/simple-names-are-not-so-simple-part-two/

    https://ericlippert.com/2014/09/25/confusing-errors-for-a-confusing-feature-part-one/

    https://ericlippert.com/2014/09/29/confusing-errors-for-a-confusing-feature-part-two/

    https://ericlippert.com/2014/10/03/confusing-errors-for-a-confusing-feature-part-three/

    在第三部分的结尾,我注意到这个功能和“颜色颜色”功能之间也有交互——也就是说,该功能允许:
    class C
    {
      Color Color { get; set; }
      void M()
      {
        Color = Color.Red;
      }
    }
    

    这里我们使用了简单的名称 Color引用 this.Color和枚举类型 Color ;根据对规范的严格阅读,这应该是一个错误,但在这种情况下,规范是错误的,目的是允许它,因为这段代码是明确的,让开发人员更改它会令人烦恼。

    我从来没有写过那篇文章来描述这两个规则之间所有奇怪的相互作用,现在这样做有点毫无意义!

    关于c# - 为什么我可以声明一个与父作用域中的变量同名的子变量?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58639477/

    相关文章:

    c# - 性能数组乘法 Pearson

    c# - 动态面板元素添加和滚动条

    java - 无法在 onSaveInstanceState 中 bundle 数据

    inheritance - 类方法在javascript中是如何实现的?

    c# - Entity Framework 在表拆分中保存一对一关系

    c# - 如何将弯曲的文本渲染成位图?

    c# - 如何通过 Lambda 或 LINQ 从列表中获取不同的实例

    C++ 使用 find_if 查找值

    c++ - 由 lambda 初始化的函数局部静态函数对象,线程安全与否?

    javascript - NodeJS 脚本中的变量自动重置为其初始值?