为什么可以';t一个类在C#中扩展它自己的嵌套类

本文关键字:一个 扩展 嵌套 自己的 它自己 为什么 | 更新日期: 2023-09-27 17:48:48

例如:

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

它从编译器中生成此错误:

循环基类依赖项涉及"A"answers"A.B"

我一直认为嵌套类的行为就像普通类一样,只是有关于访问外部类的私有成员的特殊规则,但我猜这两个类之间存在某种隐式继承?

为什么可以';t一个类在C#中扩展它自己的嵌套类

据我所知,没有涉及隐式继承。我本以为这会好起来的——尽管如果A和B是通用的,我可以想象会有什么奇怪的。

规范第10.1.4节规定:

当类别B源自类别a时,对于a来说,这是一个编译时错误取决于B.一个班直接取决于在其直接基类(如果有)上,以及直接取决于它会立即嵌套(如果任何)。给定此定义一个类依赖是传递性的的闭包直接取决于关系

我已经强调了相关部分。

这解释了编译器拒绝它的原因,但不是语言禁止它的原因。我想知道是否有CLI限制。。。

编辑:好的,我收到了埃里克·利珀特的回复。基本上,这在技术上是可能的(CLI中没有禁止它),但是:

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

在电子邮件线程上也注意到,这将使这种事情有效:

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

但如果B来源于A.,这将已经有效(正如Tinister所指出的)

嵌套+继承=奇怪。。。

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

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

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

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

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

这在当时看起来很巧妙,但回想起来我不太确定。。。

我翻遍了谷歌,没有找到任何关于它的好讨论,所以我想把它发布在这里。

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

我认为嵌套是为了表示嵌套类型是嵌套类型定义的一部分。有了这种解释,这种限制是有意义的,因为当编译器达到A的定义时,A。B还没有定义,即使在A的末尾,它也已经按照A定义了。

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

代替:

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() {
      ...
   }
}

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