为什么 C# 中的类不能扩展它自己的嵌套类?

发布于 2024-07-09 09:36:36 字数 232 浏览 6 评论 0原文

例如:

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

编译器会生成此错误:

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

我总是认为嵌套类的行为就像常规类一样,除了有关访问外部类的私有成员的特殊规则,但我猜这两个类之间存在一些隐式继承?

For example:

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

Which generates this error from the compiler:

Circular base class dependency
involving 'A' and 'A.B'

I always figured a nested class behaved just like a regular class except with special rules concerning accessing the outer class's private members, but I guess there's some implicit inheritance occurring between the two classes?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

挽你眉间 2024-07-16 09:36:36

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

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

当 B 类派生自 A 类时,
这是 A 的编译时错误
依赖B.A类直接依赖
在其直接基类(如果有)上并且
直接取决于内部的类
它立即嵌套
(如果
任何)。 鉴于这个定义,
完整的类集,其中
class dependent 是传递性的
的关闭直接取决于
关系。

我已经突出显示了相关部分。

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

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

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

电子邮件线程中还指出,这将使此类事情有效:

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

...但是如果 B 派生自 A,那么这已经(如 Tinister 所指出的)有效。

嵌套 + 继承 = 奇怪...

There's no implicit inheritance involved as far as I can tell. I would have expected this to be okay - although I can imagine weirdness if A and B were generic.

It's specified in section 10.1.4 of the spec:

When a class B derives from a class A,
it is a compile-time error for A to
depend on B. A class directly depends
on its direct base class (if any) and
directly depends on the class within
which it is immediately nested
(if
any). Given this definition, the
complete set of classes upon which a
class depends is the transitive
closure of the directly depends on
relationship.

I've highlighted the relevant section.

That explains why the compiler is rejecting it, but not why the language prohibits it. I wonder if there's a CLI restriction...

EDIT: Okay, I've had a response from Eric Lippert. Basically, it would be technically possible (there's nothing in the CLI to prohibit it), but:

  • Allowing it would be difficult in the compiler, invalidating various current assumptions around ordering and cycles
  • It's a pretty odd design decision which is easier to prohibit than to support

It was also noted on the email thread that it would make this kind of thing valid:

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

... but that would already (as noted by Tinister) be valid if B derived from A.

Nesting + inheritance = oddness...

坏尐絯 2024-07-16 09:36:36

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

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

This is not a C# thing as much as it is a compiler thing. One of the jobs of a compiler is to lay out a class in memory, that is a bunch of basic data types, pointers, function pointers and other classes.

It can't construct the layout for class A until it knows what the layout of class B is. It can't know what the layout of class B is until it finished with the layout of class A. Circular dependency.

幻梦 2024-07-16 09:36:36

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

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

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

    private AA _containedObject;
}

当时看起来相当圆滑,但回想起来我不太确定......

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

但是,在 Eric Lippert 博客上的帖子 他给出了一个实现嵌套接口的类的示例,以及一个以嵌套类作为类型参数实现通用接口的类的示例(该类无法编译,他调用了“当前编译器中的错误”)。 这两个例子都涉及接口,所以我想知道嵌套类是否有一些特殊的规则。 似乎是有的。

Regarding questions about what I was attempting to do:

Basically, I wanted to create a class that had a composition relationship with itself, but I didn't want to have the contained object to contain other objects and therefore create a chain with many "A has-a A has-a A has-a A has-a..." relationships. So my thought at the time was do something like this:

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

    private AA _containedObject;
}

Which at the time seemed pretty slick but in retrospect I'm not so sure...

I had rummaged through Google and didn't find any good discussion on it so I thought I'd post it here.

However, within the comments of a post at Eric Lippert's Blog he gives examples of a class implementing a nested interface as well as a class implementing a generic interface with a nested class as the type argument (which doesn't compile and he calls a "bug" in the current compiler). Both of those examples concern interfaces so I was wondering if there was some special rules with nested classes. And it seems there are.

羞稚 2024-07-16 09:36:36

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

I think the nesting is meant to represent that the nested type is part of the definition of the nesting type. With that interpretation, the limitation makes sense because at the time the compiler hits the definition of A, A.B is not yet defined, and even at the end of A, it is already defined in terms of A.B.

风吹雨成花 2024-07-16 09:36:36

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

而不是:

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

I was able to avoid this (at least with interfaces) by inheriting from a separate class containing the nested interfaces. (In my scenario I am also returning references to these interfaces.)

Instead of:

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

Do something like this:

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

To avoid the ugliness with explicit interface implementations, you can also inherit from the other class, though that wouldn't work if you were trying to inherit from a nested class, since you can't inherit from both classes.

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() {
      ...
   }
}
若沐 2024-07-16 09:36:36

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

This makes no sense to me... You are trying to extend something that doesn't exist !!! Class B only exists in the scope of class A and because of this I think there is some kind of inheritance.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文