109

我有一堂课,当我尝试在另一堂课中使用它时,我收到以下错误。

using System;
using System.Collections.Generic;
using System.Linq;

namespace MySite
{
    public class Reminders
    {
        public Dictionary<TimeSpan, string> TimeSpanText { get; set; }

        // We are setting the default values using the Costructor
        public Reminders()
        {
            TimeSpanText.Add(TimeSpan.Zero, "None");
            TimeSpanText.Add(new TimeSpan(0, 0, 5, 0), "5 minutes before");
            TimeSpanText.Add(new TimeSpan(0, 0, 15, 0), "15 minutes before");
            TimeSpanText.Add(new TimeSpan(0, 0, 30, 0), "30 minutes before");
            TimeSpanText.Add(new TimeSpan(0, 1, 0, 0), "1 hour before");
            TimeSpanText.Add(new TimeSpan(0, 2, 0, 0), "2 hours before");
            TimeSpanText.Add(new TimeSpan(1, 0, 0, 0), "1 day before");
            TimeSpanText.Add(new TimeSpan(2, 0, 0, 0), "2 day before");
        }

    }
}

在另一个类中使用该类

class SomeOtherClass
{  
    private Reminders reminder = new Reminders();
    // error happens on this line:
    private dynamic defaultReminder = reminder.TimeSpanText[TimeSpan.FromMinutes(15)]; 
    ....

错误(CS0236):

A field initializer cannot reference the nonstatic field, method, or property

为什么会发生以及如何解决?

4

4 回答 4

157

这一行:

private dynamic defaultReminder = 
                          reminder.TimeSpanText[TimeSpan.FromMinutes(15)];

您不能使用实例变量来初始化另一个实例变量。为什么?因为编译器可以重新排列这些——不能保证reminder之前会被初始化defaultReminder,所以上面的行可能会抛出一个NullReferenceException.

相反,只需使用:

private dynamic defaultReminder = TimeSpan.FromMinutes(15);

或者,在构造函数中设置值:

private dynamic defaultReminder;

public Reminders()
{
    defaultReminder = reminder.TimeSpanText[TimeSpan.FromMinutes(15)]; 
}

MSDN - Compiler Error CS0236上有关于此编译器错误的更多详细信息。

于 2013-01-21T13:02:34.320 回答
25

您需要将该代码放入类的构造函数中:

private Reminders reminder = new Reminders();
private dynamic defaultReminder;

public YourClass()
{
    defaultReminder = reminder.TimeSpanText[TimeSpan.FromMinutes(15)];
}

原因是您不能使用一个实例变量来使用字段初始化程序来初始化另一个实例变量。

于 2013-01-21T13:02:50.840 回答
11

你可以这样使用

private dynamic defaultReminder => reminder.TimeSpanText[TimeSpan.FromMinutes(15)]; 
于 2016-08-06T16:17:21.390 回答
6

private dynamic defaultReminder = reminder.TimeSpanText[TimeSpan.FromMinutes(15)];是一个字段初始化器并首先执行(在没有初始化器的任何字段设置为其默认值之前以及在执行调用的实例构造函数之前)。没有初始化器的实例字段只有在所有实例字段初始化器完成后才会有一个合法的(默认)值。由于初始化顺序,实例构造函数最后执行,这就是为什么在执行初始化程序时还没有创建实例的原因。因此,编译器不允许在类实例完全构造之前引用任何实例属性(或字段)。这是因为任何对实例变量的访问,例如reminder隐式引用实例 ( this),以告诉编译器要使用的实例的具体内存位置。

这也是this不允许在实例字段初始化器中使用的原因。

实例字段的变量初始值设定项不能引用正在创建的实例。因此,在变量初始化器中引用 this 是编译时错误,因为变量初始化器通过 simple_name引用任何实例成员是编译时错误。

唯一保证在执行实例字段初始化程序之前初始化的类型成员是类(静态)字段初始化程序和类(静态)构造函数和类方法。由于静态成员是独立于实例的,因此可以随时引用它们:

class SomeOtherClass
{
  private static Reminders reminder = new Reminders();

  // This operation is allowed,
  // since the compiler can guarantee that the referenced class member is already initialized
  // when this instance field initializer executes
  private dynamic defaultReminder = reminder.TimeSpanText[TimeSpan.FromMinutes(15)];
}

这就是为什么实例字段初始化器只允许引用一个类成员(静态成员)。此编译器初始化规则将确保确定性类型实例化。

有关更多详细信息,我推荐此文档:Microsoft Docs:类声明

这意味着引用另一个实例成员以初始化其值的实例字段必须从实例构造函数初始化,或者必须声明被引用的成员static

于 2019-09-02T21:23:03.973 回答