使用父保护构造函数实例化子类字段
Instance subclass field using parent protected constructor
简化情况
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();
}
}
为什么无法使用 class 受保护的构造函数在 class B 中创建 A 的实例?
在我看来,受保护的构造函数就像受保护的方法,所以应该可以在子class.
中运行它
Why it's impossible to create instance of A in class B using class A
protected constructor?
您不能使用new
修饰符调用受保护的构造函数,因为受保护的构造函数的目的是它只能从派生 类 的角度调用,因此从 "outside" 看不到。
编译器不会推断对 new A()
的调用是从 B
的实例完成的。这就是构造函数语法可用的原因,以保证如何调用基本构造函数的约定。
在为 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
一种骇人听闻的方法(我会避免这样做)是创建这样一个实例,可以通过 Activator.CreateInstance
重载来实现,它接受一个 bool
标志,指示构造函数是非 public:
var b = (B)Activator.CreateInstance(typeof(B), nonPublic: true);
你可以构造构造函数A
protected internal
:
public class A
{
protected internal A() { }
protected A Make() { return new A(); }
}
因此类型或成员可以被声明它的程序集中的任何代码访问,或者从 派生的 class 在另一个程序集中。
查看此 link 了解更多详情:Many Questions: Protected Constructors
。
尝试修改代码为
a = this.Make();
希望它能帮助您更好地理解代码。每 MSDN
A protected member is accessible within its class and by derived class instances.
因此,当您调用 this.Make()
时,您正在访问 derived class instances
中的 protected constructor
。当你在class B
里面调用new A()
时,当前实例this
和要创建的新实例是两个不同的实例。您实际上是在 A
或 A
派生的 class.
之外访问 A
的构造函数
protected
成员在派生 class (subclass) 中只能通过派生 class 类型的实例引用(或进一步派生class).
这是一个使用方法而不是构造函数的示例:
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
里面调用M
C
.
您使用实例构造函数的示例是类似的。 new
对象表达式就像在 new
.
之后编写的类型的(新)对象上调用实例成员(实例构造函数)
简化情况
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();
}
}
为什么无法使用 class 受保护的构造函数在 class B 中创建 A 的实例?
在我看来,受保护的构造函数就像受保护的方法,所以应该可以在子class.
中运行它Why it's impossible to create instance of A in class B using class A protected constructor?
您不能使用new
修饰符调用受保护的构造函数,因为受保护的构造函数的目的是它只能从派生 类 的角度调用,因此从 "outside" 看不到。
编译器不会推断对 new A()
的调用是从 B
的实例完成的。这就是构造函数语法可用的原因,以保证如何调用基本构造函数的约定。
在为 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
一种骇人听闻的方法(我会避免这样做)是创建这样一个实例,可以通过 Activator.CreateInstance
重载来实现,它接受一个 bool
标志,指示构造函数是非 public:
var b = (B)Activator.CreateInstance(typeof(B), nonPublic: true);
你可以构造构造函数A
protected internal
:
public class A
{
protected internal A() { }
protected A Make() { return new A(); }
}
因此类型或成员可以被声明它的程序集中的任何代码访问,或者从 派生的 class 在另一个程序集中。
查看此 link 了解更多详情:Many Questions: Protected Constructors
。
尝试修改代码为
a = this.Make();
希望它能帮助您更好地理解代码。每 MSDN
A protected member is accessible within its class and by derived class instances.
因此,当您调用 this.Make()
时,您正在访问 derived class instances
中的 protected constructor
。当你在class B
里面调用new A()
时,当前实例this
和要创建的新实例是两个不同的实例。您实际上是在 A
或 A
派生的 class.
A
的构造函数
protected
成员在派生 class (subclass) 中只能通过派生 class 类型的实例引用(或进一步派生class).
这是一个使用方法而不是构造函数的示例:
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
里面调用M
C
.
您使用实例构造函数的示例是类似的。 new
对象表达式就像在 new
.