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

时间:2015-10-27 09:19:41

标签: 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 due to protection level
        a = new A(); //inaccessible due to protection level
        a = Make();
    }
}

为什么使用A类保护构造函数在B类中创建A的实例是不可能的?

在我看来,受保护的构造函数就像受保护的方法,因此应该可以在子类中运行它。

4 个答案:

答案 0 :(得分:5)

  

为什么使用A类在B类中创建A的实例是不可能的   受保护的构造函数?

无法使用new修饰符调用受保护的构造函数,因为受保护的构造函数的目的是只能从派生中调用它类的观点,因此从“外部”看不到。

编译器不会推断从new A()的实例调用B。这就是构造函数语法可用的原因,以保证如何调用基础构造函数的约定。

在为A声明构造函数时,可以调用 B构造函数:

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

一种hackish方式(我会避免这样做)是创建这样一个实例可以用Activator.CreateInstance重载实现,它接受一个bool标志,表明构造函数是非公共的:

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

答案 1 :(得分:3)

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

public class A
{
    protected internal A() { }
    protected A Make() { return new A(); }
}

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

有关详细信息,请查看此链接:Many Questions: Protected Constructors

答案 2 :(得分:2)

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
  }
}

因此,在上面的示例中,您可以在M内的C上拨打C,但无法在MB拨打C 1}}。

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

答案 3 :(得分:0)

尝试将代码修改为

a = this.Make();

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

  

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

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