C# Eric Lippert所说的“是什么意思?”;您需要知道基类是什么来确定基类是什么;?

C# Eric Lippert所说的“是什么意思?”;您需要知道基类是什么来确定基类是什么;?,c#,language-design,C#,Language Design,我刚读了Eric Lippert写的这篇有趣的文章。接近尾声时,他说: 在前面提到的冒号后面解析名称的规则不适用 有理有据;你可能会在需要知道什么的情况下结束 基类用于确定基类是什么 冒号表示继承运算符(例如,Dog:Animal) 埃里克指的是什么情况?有人能提供代码示例吗?这可能发生在具有泛型、继承和嵌套类的复杂场景中: class Base<T> { public class Inner {} } class Derived : Base<Derived.Inn

我刚读了Eric Lippert写的这篇有趣的文章。接近尾声时,他说:

在前面提到的冒号后面解析名称的规则不适用 有理有据;你可能会在需要知道什么的情况下结束 基类用于确定基类是什么

冒号表示继承运算符(例如,
Dog:Animal


埃里克指的是什么情况?有人能提供代码示例吗?

这可能发生在具有泛型、继承和嵌套类的复杂场景中:

class Base<T> {
    public class Inner {}
}

class Derived : Base<Derived.Inner2> {
    public class Inner2 : Inner {}
}
类基{
公共类内部{}
}
派生类:基{
公共类Inner2:内部{}
}

  • 要确定
    Derived
    的基类,我们需要绑定
    Derived.Inner2
  • 要绑定
    派生的.Inner2
    ,我们需要解析
    内部
    符号
  • 内部
    符号继承自其包含范围的基类,因此我们需要再次确定
    派生的
    基类

    • SLaks给出了一个很好的答案;请参阅我的评论以了解更多说明

      正如我在评论中所说,我正在寻找关于这个主题的旧笔记,如果我找到了,我会写一个博客。下面是一个有趣的附加示例。这个节目是合法的。类声明和字段声明中的
      N
      的含义相同还是不同?如果它们相同,那么什么是它们的完全限定类型表达式?如果它们不同,为什么规范要求它们不同

      public class N {}
      public class B<T> 
      {
          public class N {}
      }
      
      public class D : B<N> // base class
      {
        N n;  // field
      }
      
      公共类N{}
      公共B级
      {
      公共类N{}
      }
      公共类D:B//基类
      {
      N;//字段
      }
      
      这说明了基本问题:名称查找要求基类是已知的,但基类是按名称查找的


      现在想想界面在混合中是如何工作的。假设类
      D
      也在
      中实现了一个接口
      ,类似地嵌套在
      B
      中,并且全局可用。接口查找是否解析为基类或全局命名空间?这些是编写编译器时必须解决的问题。

      为什么不在本文的评论中提出这些问题呢。你会有更好的机会让Eric看到,而且只有他才能回答他的意思。还有他的链接。@MenelaosVergis:我很确定这不是一个错误。@MenelaosVergis:可能,但我也不明白。如果不是打字错误,那就是自相矛盾。你不能(或毫无意义地)确定你已经知道了什么。是的,这是矛盾,这意味着算法没有很好的基础。@JamesWebster:那不是真的;他只是问基类怎么会模棱两可。答案很好。使用此代码和
      ToString
      @IanNewson玩得很开心:谢谢!TryRoslyn(见我的链接)实际上是一种更方便的方式来了解发生了什么。@IanNewson:我花了很多很多天找到了十几个不同的案例,其中一些案例C#没有处理好,因为错误消息错误或不一致,选择了错误的类型,等等。问题是语言规范本身不清楚;Mads和我曾试图澄清这一点,但最终添加了破坏性的更改。我们决定不在这上面花费太多的时间,因为正如您正确地指出的,暴露规范的不充分性的场景是非常不现实的。@EricLippert感谢您的输入。我完全明白为什么这种情况对实际从事编译器工作的人来说一定很恼火,但从消费者的角度来看,这不是问题,因为您的努力工作。如果我处在你的位置,我会让任何事情都变得疯狂,甚至像答案中的代码一样非法,但也许正是这种懒惰才是我不编写编译器的原因:D@SLaks当前位置我一直在找我的笔记。当(如果!)我这样做的时候,我会写一篇关于他们的博客文章。我确实记得,断开的案例通常涉及到这样的情况,即存在嵌套在基类中的三层泛型结构的类型,循环检测器会错误地检测到一个类型是循环定义的。假设一个全局namspace
      global
      B
      完全限定为
      B
      ,和
      N
      指嵌套类,因此完全限定为
      B.N。如果希望
      classed D:B
      中的
      N
      成为嵌套的
      N
      ,则必须提供一个类型参数,例如
      classed D:B
      。当然,
      sometype
      可以是
      B
      ,甚至可以是
      B.N
      ,例如
      public class D:B
      等等。我复制和粘贴了这一概念,并在大约700个嵌套的泛型级别(我希望对任何人来说都足够了…)我最终得到了错误
      用户诊断分析器“Microsoft.CodeAnalysis.CSharp.Diagnostics.SimplifyTypeNames.CsharpSimplifyTypeNamesDiagnosticanAnalyzer”抛出了类型为“System.UnficientExecutionStackException”的异常,并显示消息“堆栈不足,无法继续安全执行程序”。这可能是因为调用堆栈上的函数太多,或者堆栈上的函数使用了太多的堆栈空间。
      @Galax:事实上,C#编译器团队中曾经有一位测试人员乐于发现这样的情况,这可能会炸毁分析器。在某些情况下,我们用迭代算法取代了递归算法,在某些情况下,我们只是让它爆炸,假设这样的程序是不现实的。令人印象深刻的是,它让我走了这么远,一些工具提示花了几秒钟生成,但占用了我显示器的1/4。我记得大约10年前崩溃了VisualC++的IDE,它在嵌套的两个层次的深度上做了很多不那么令人讨厌的事情。