使用受父保护的构造函数的实例子类字段

本文关键字:构造函数 实例 子类 字段 保护 | 更新日期: 2023-09-27 18:19:28

>简化情况

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 修饰符调用受保护的构造函数,因为受保护构造函数的用途是只能从派生类的角度调用它,因此从"外部"不可见。

编译器不会推断对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标志:

var b = (B)Activator.CreateInstance(typeof(B), nonPublic: true);

你可以制作构造函数A protected internal

public class A
{
    protected internal A() { }
    protected A Make() { return new A(); }
}
因此,类型或成员

可由声明该类型或成员的程序集中的任何代码访问,也可以从另一个程序集的派生类中访问。

查看此链接以获取更多详细信息: Many Questions: Protected Constructors .

protected成员

只能在派生类(子类(中通过派生类(或进一步派生类(类型的实例引用来访问。

下面是一个使用方法而不是构造函数的示例:

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,但不能在C内部的B上调用M

实例构造函数的示例与此类似。new对象表达式就像在 new 之后编写的类型(新(对象上调用实例成员(实例构造函数(。

尝试将代码修改为

a = this.Make();

希望它可以帮助您更好地理解代码。根据 MSDN

受保护的成员可以在其类中访问,也可以由派生类实例访问。

因此,当您调用this.Make()时,您正在derived class instances中访问protected constructor。在 class B 中调用 new A() 时,当前实例this和要创建的新实例是两个不同的实例。您实际上是在AA派生类之外访问A的构造函数。