Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/266.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 使用父保护构造函数的实例子类字段_C#_Inheritance_Constructor_Field_Protected - Fatal编程技术网

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