【问题标题】:What is static about a base constructor call? [duplicate]基本构造函数调用的静态是什么? [复制]
【发布时间】:2013-07-10 00:34:06
【问题描述】:

以下 C# 代码无法编译。

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

public class DerivedType : BaseType
{
    private int foo;

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

在调用 DerivedType 的基本构造函数时发生错误,并显示消息“无法在静态上下文中访问非静态字段 'foo'”。这个错误信息告诉我什么? 'foo' 不是静态的,类也不是,它们也不是静态构造函数。

【问题讨论】:

  • 我不认为它完全重复,但这是一个非常有用的链接,谢谢@mikez。

标签: c# compiler-errors


【解决方案1】:

base(foo = 0) 执行时,DerivedType 类尚未“创建”,因此它无法访问它定义的成员。

事情发生的顺序是这样的

  1. 用户拨打new DerivedType()
  2. 代码调用DerivedType的base(foo = 0)
  3. 代码调用BaseType的隐式base()Object()
  4. Object 中的任何字段分配内存,然后Object() 构造函数运行完成。
  5. BaseType 中的任何字段分配内存,然后BaseType(int bar) 构造函数运行完成。
  6. DerivedType 中的任何字段分配内存,然后DerivedType() 构造函数运行完成。

所以您看到您正尝试在第 2 步为 foo 分配一个值,但 foo 直到第 6 步才会存在。

【讨论】:

    【解决方案2】:

    问题是构造函数还没有运行。

    在构造基本类型之前,您无法访问您的实例。

    【讨论】:

    • 我喜欢你的表达方式!!错误的奇怪部分是它发生在实例之外是静态上下文。
    • 从技术上讲,您可以在基构造函数完成之前访问实例字段:在基类中创建一个虚拟方法并从基构造函数调用它,在派生类中覆盖访问该实例字段。
    • @fcuesta:是的,但基础构造函数将启动
    【解决方案3】:

    错误说foo不是静态的,但只有类的静态成员和构造函数本身的参数可以用于调用基构造函数(除了其他外部常量)。

    你可能是说

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

    非常准确地摘自 C# 文档:C# 5.0 规范的第 10.11.1 节“构造函数初始化程序”。

    允许访问构造函数本身的参数:

    实例构造函数声明的形式参数列表给出的参数范围包括该声明的构造函数初始值设定项。因此,允许构造函数初始化器访问构造函数的参数。

    但不允许访问实例和实例字段:

    实例构造函数初始化程序无法访问正在创建的实例。因此,在构造函数初始化程序的参数表达式中引用 this 是编译时错误,因为参数表达式通过简单名称引用任何实例成员也是编译时错误

    【讨论】:

    • 是的;他在问为什么
    • @SLaks - 我从 C# 规范中添加了限制。我对“为什么以这种方式设计”没有任何见解(通常超出 SO 范围),限制对我来说也很自然。
    • @AlexeiLevenkov 在我链接到的可能副本中看到 Eric Lippert 的答案。它解释了为什么以这种方式设计语言。
    猜你喜欢
    • 2013-12-04
    • 1970-01-01
    • 2011-08-13
    • 2012-02-28
    • 1970-01-01
    • 2011-06-06
    • 1970-01-01
    • 1970-01-01
    • 2013-12-25
    相关资源
    最近更新 更多