C# 使用父保护构造函数的实例子类字段
简化情况C# 使用父保护构造函数的实例子类字段,c#,inheritance,constructor,field,protected,C#,Inheritance,Constructor,Field,Protected,简化情况 public class A { protected A() { } protected A Make() { return new A(); } } public class B : A { A a = new A(); //inaccessible due to protection level B b = new B(); private B() { A c = new A();//inaccessible du
public class A {
protected A() { }
protected A Make() { return new A(); }
}
public class B : A {
A a = new A(); //inaccessible due to protection level
B b = new B();
private B()
{
A c = new A();//inaccessible due to protection level
a = new A(); //inaccessible due to protection level
a = Make();
}
}
为什么不可能使用类A受保护的构造函数在类B中创建实例A
在我看来,受保护的构造函数就像受保护的方法,所以应该可以在子类中运行它
为什么不可能使用类A在类B中创建A的实例
受保护的构造函数
不能使用new
修饰符调用受保护的构造函数,因为受保护的构造函数的目的是只能从派生类的角度调用它,因此从“外部”看不到它
编译器不会从B
的实例推断对new A()
的调用正在进行。这就是为什么构造函数语法可用,以保证如何调用基本构造函数的约定
为B
声明构造函数时,可以调用A
构造函数:
public B(string foo) : base(foo)
这是代表默认构造函数实际执行的操作。例如:
public class A {}
public class B : A
{
public B() {}
}
将产生以下IL:
// Methods
.method public hidebysig specialname rtspecialname
instance void .ctor () cil managed
{
// Method begins at RVA 0x205a
// Code size 7 (0x7)
.maxstack 8
IL_0000: ldarg.0
IL_0001: call instance void A::.ctor() <--- This.
IL_0006: ret
} // end of method B::.ctor
您可以使构造函数
A
:
因此,类型或成员可以由声明它的程序集中的任何代码访问,也可以从另一个程序集中的派生类中访问
查看此链接了解更多详细信息:。尝试将代码修改为
a = this.Make();
希望它能帮助您更好地理解代码。
受保护的成员可以在其类内以及由派生类实例访问
因此,当您调用
this.Make()
时,您正在访问派生类实例中的受保护构造函数
。当您在class B
内部调用new A()
时,当前实例this
和要创建的新实例是两个不同的实例。实际上,您正在A
或A
的派生类之外访问A
的构造函数。受保护的
成员只能通过派生类(或其他派生类)类型的实例引用在派生类(子类)中访问
下面是一个使用方法而不是构造函数的示例:
class B
{
protected void M() { }
}
class C : B
{
void X()
{
M(); // OK, same as this.M()
}
void Y(C otherC)
{
otherC.M(); // OK
}
void Z(B otherB)
{
otherB.M(); // compile-time error CS1540
}
}
因此,在上面的示例中,您可以在C
内部C
上调用M
,但不能在B
内部C
上调用M
您的实例构造函数示例与此类似。new
对象表达式就像在new
之后写入的类型的(新)对象上调用实例成员(实例构造函数)对于调用基本构造函数,您可以private B():base()
您可以提供完整的错误消息吗?嗯,我遇到另一个错误:无法访问受保护的成员'A.A()'通过类型为'a'的限定符;在VS Community 2015中,限定符的类型必须是“B”(或派生自它)完整消息:“错误CS0122'A.A()'由于其保护级别而不可访问”,但在OP中,B
class具有基类字段,并尝试初始化它。@Grundy确切地说,他不能这样做。这就是我在回答中所说的:)可能,我只是错过了你答案中的main:-)我想你说的只是调用A
构造函数作为B
的基,而不是init字段,所以这意味着我只能通过在子类中使用:base()
来使用父类保护的构造函数?@JCode是的,你可以。这正是它的目的。@Grundy,我没有说Make
不起作用。我想让OP在上下文中理解这一点。
a = this.Make();
class B
{
protected void M() { }
}
class C : B
{
void X()
{
M(); // OK, same as this.M()
}
void Y(C otherC)
{
otherC.M(); // OK
}
void Z(B otherB)
{
otherB.M(); // compile-time error CS1540
}
}