32

例如:

public class A : A.B
{
    public class B { }
}

从编译器生成此错误:

涉及“A”和“AB”的循环基类依赖

我一直认为嵌套类的行为就像一个普通类,除了关于访问外部类的私有成员的特殊规则,但我猜这两个类之间发生了一些隐式继承?

4

6 回答 6

34

据我所知,不涉及隐式继承。我本以为这会没事的——尽管如果 A 和 B 是通用的,我可以想象会很奇怪。

它在规范的第 10.1.4 节中指定:

当类 B 派生自类 A 时,A 依赖于 B 是编译时错误。一个类直接依赖于它的直接基类(如果有的话)并且 直接依赖于它立即嵌套的类(如果有)。给定这个定义,一个类所依赖的完整类集是直接依赖关系的传递闭包。

我已经强调了相关部分。

这解释了为什么编译器拒绝它,但不能解释为什么语言禁止它。我想知道是否有 CLI 限制...

编辑:好的,我收到了 Eric Lippert 的回复。基本上,这在技术上是可行的(CLI 中没有禁止它的内容),但是:

  • 在编译器中允许它会很困难,使当前关于排序和循环的各种假设无效
  • 这是一个非常奇怪的设计决定,禁止比支持更容易

电子邮件线程上还指出,它会使这种事情有效:

A.B x = new A.B.B.B.B.B.B.B.B.B.B.B.B();

...但是如果 B 从 A 派生,那已经(如 Tinister 所述)是有效的。

嵌套+继承=奇怪...

于 2008-11-05T16:01:16.867 回答
13

这不是 C# 的事情,而是编译器的事情。编译器的工作之一是在内存中布局一个类,即一堆基本数据类型、指针、函数指针和其他类。

在知道 B 类的布局是什么之前,它不能为 A 类构造布局。在完成A类的布局之前,它无法知道B类的布局是什么。循环依赖。

于 2008-11-05T16:17:29.873 回答
1

关于我试图做什么的问题:

基本上,我想创建一个与自身具有组合关系的类,但我不想让包含的对象包含其他对象,因此创建一个包含许多“A has-a A has-a A has-”的链一个有一个...”的关系。所以我当时的想法是做这样的事情:

public class A : A.AA
{
    public class AA
    {
        // All of the class's logic
    }

    private AA _containedObject;
}

当时看起来很漂亮,但回想起来我不太确定......

我翻遍了谷歌并没有找到任何好的讨论,所以我想我会把它贴在这里。

然而,在 Eric Lippert 博客上的一篇文章的评论中,他给出了一个实现嵌套接口的类以及一个实现泛型接口的类的示例,其中嵌套类作为类型参数(它不会编译,他称之为“错误”在当前编译器中)。这两个例子都涉及接口,所以我想知道嵌套类是否有一些特殊规则。似乎有。

于 2008-11-05T16:53:20.160 回答
0

我认为嵌套是为了表示嵌套类型是嵌套类型定义的一部分。通过这种解释,限制是有道理的,因为在编译器达到 A 的定义时,AB 尚未定义,甚至在 A 的末尾,它已经根据 AB 定义

于 2008-11-05T16:17:14.103 回答
0

通过从包含嵌套接口的单独类继承,我能够避免这种情况(至少使用接口)。(在我的场景中,我还返回对这些接口的引用。)

代替:

public class MyClass<T1, T2, T3> :
   MyClass<T1, T2, T3>.Interface
where T1 : ...
where T2 : ... 
where T3 : ... {
   public interface Interface { Interface SomeMethod(); }

   Interface Interface.SomeMethod() {
      ...
   }
}

// compile error: Circular base class dependency

做这样的事情:

public sealed class MyClassInterfaces<T1, T2, T3>
where T1 : ...
where T2 : ... 
where T3 : ... {
   public interface Interface { Interface SomeMethod(); }
}

sealed class MyClass<T1, T2, T3> :
   MyClassInterfaces<T1, T2, T3>.Interface
where T1 : ...
where T2 : ... 
where T3 : ... {
   MyClassInterfaces<T1, T2, T3>.Interface
   MyClassInterfaces<T1, T2, T3>.Interface.SomeMethod() {
      ...
   }
}

为了避免显式接口实现的丑陋,您还可以从另一个类继承,尽管如果您尝试从嵌套类继承,那将不起作用,因为您不能从两个类继承。

public abstract class MyClassInterfaces<T1, T2, T3>
where T1 : ...
where T2 : ... 
where T3 : ... {
   public interface Interface { Interface SomeMethod(); }
}

sealed class MyClass<T1, T2, T3> :
   MyClassInterfaces<T1, T2, T3>,
   MyClassInterfaces<T1, T2, T3>.Interface
where T1 : ...
where T2 : ... 
where T3 : ... {
   Interface Interface.SomeMethod() {
      ...
   }
}
于 2016-08-29T02:22:18.530 回答
-2

这对我来说毫无意义......您正在尝试扩展不存在的东西!B 类只存在于 A 类的范围内,因此我认为存在某种继承。

于 2008-11-05T16:15:46.603 回答