What is static about a base constructor call? [dup

2019-02-25 02:13发布

问题:

This question already has an answer here:

  • Cannot access non-static field 2 answers

The following C# code does not compile.

public class BaseType
{
    public BaseType(int bar)
    {
        // Do stuff with bar...
    }
}

public class DerivedType : BaseType
{
    private int foo;

    public DerivedType() : base(foo = 0) {}
}

The error occurs on the call to DerivedType's base constructor, with the message "Cannot access non-static field 'foo' in static context." What is this error message telling me? 'foo' is not static, and neither are the classes, and these are not static constructors.

回答1:

At the point that base(foo = 0) executes the DerivedType class has not been "Created" yet so it can not access the members it defines yet.

The order things happen is like this

  1. The user calls new DerivedType()
  2. The code calls DerivedType's base(foo = 0)
  3. The code calls BaseType's implicit base() to Object()
  4. The memory for any fields in Object is allocated and then the Object() constructor is run to completion.
  5. The memory for any fields in BaseType is allocated and then the BaseType(int bar) constructor is run to completion.
  6. The memory for any fields in DerivedType is allocated and then the DerivedType() constructor is run to completion.

So you see you are attempting to assign a value to foo at step 2, but foo won't exist till step 6.



回答2:

The problem is that the constructor hasn't run yet.

You cannot access your instance until its base type has been constructed.



回答3:

The error says that foo is not static, but only static members of the class and parameters of constructor itself can be used in call to base constructor (in addition to other external constants).

You probably mean

public DerivedType() : base(0) {
   foo = 0;       
}

To be very precise following in excerpt from C# documentation: section 10.11.1 "Constructor initializers" of C# 5.0 specification.

Access to parameters of the constructor itself allowed:

The scope of the parameters given by the formal-parameter-list of an instance constructor declaration includes the constructor initializer of that declaration. Thus, a constructor initializer is permitted to access the parameters of the constructor.

But access to instance and hence instance fields is not allowed:

An instance constructor initializer cannot access the instance being created. Therefore it is a compile-time error to reference this in an argument expression of the constructor initializer, as is it a compile-time error for an argument expression to reference any instance member through a simple-name