我正在将一些 Java 代码移植到 C#,我遇到了这个用于复制对象的习惯用法:
class Base
{
int x;
public Base(int x) { this.x = x; }
protected Base(Base other) { x = other.x; }
}
class Derived : Base
{
Base foo;
public Derived(Derived other)
: base(other)
{
foo = new Base(other.foo); // Error CS1540
}
}
错误 CS1540 为:
Cannot access protected member 'Base.Base(Base)' via a qualifier of type 'Base'; the qualifier must be of type 'Derived' (or derived from it)
我理解这个错误的目的:它阻止访问兄弟类型的 protected 成员。但是 Base.Base(Base) 显然不会在兄弟类型上被调用!这只是没有包含在规范中,还是我遗漏了一些不安全的原因?
编辑:啊,成语是 new Base(other.foo)
而不是 new Base(other)
最佳答案
语言规范的第 3.5.2 节和第 3.5.3 节详细说明了这一点,为方便起见,我将发布 3.5.2(它更短!)并让您自己找到 3.5.3。
In intuitive terms, when a type or member M is accessed, the following steps are evaluated to ensure that the access is permitted:
- First, if M is declared within a type (as opposed to a compilation unit or a namespace), a compile-time error occurs if that type is not accessible.
- Then, if M is public, the access is permitted.
- Otherwise, if M is protected internal, the access is permitted if it occurs within the program in which M is declared, or if it occurs within a class derived from the class in which M is declared and takes place through the derived class type (§3.5.3).
- Otherwise, if M is protected, the access is permitted if it occurs within the class in which M is declared, or if it occurs within a class derived from the class in which M is declared and takes place through the derived class type (§3.5.3).
- Otherwise, if M is internal, the access is permitted if it occurs within the program in which M is declared.
- Otherwise, if M is private, the access is permitted if it occurs within the type in which M is declared.
- Otherwise, the type or member is inaccessible, and a compile-time error occurs.
基本上,访问基类的 protected 成员必须通过派生类的实例。正如您所说, sibling 不能访问彼此的 protected 成员,但是语言规范还禁止 child 访问基的 protected 成员,除非引用是通过 child 进行的。
关于c# - 为什么子类不能使用基类保护的构造函数创建新对象?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6223111/