[c#] 필드 이니셜 라이저는 비 정적 필드, 메서드 또는 속성을 참조 할 수 없습니다.

클래스가 있는데 다른 클래스에서 사용하려고하면 아래와 같은 오류가 발생합니다.

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

왜 발생하고 어떻게 해결합니까?



답변

이 줄 :

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에 있습니다.


답변

해당 코드를 클래스 생성자에 넣어야합니다.

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

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

그 이유는 하나의 인스턴스 변수를 사용하여 필드 이니셜 라이저를 사용하여 다른 변수를 초기화 할 수 없기 때문입니다.


답변

이렇게 사용할 수 있습니다

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


답변

private dynamic defaultReminder = reminder.TimeSpanText[TimeSpan.FromMinutes(15)];필드 이니셜 라이저이고 먼저 실행됩니다 (이니셜 라이저가없는 필드가 기본값으로 설정되기 전과 호출 된 인스턴스 생성자가 실행되기 전). 이니셜 라이저가없는 인스턴스 필드는 모든 인스턴스 필드 이니셜 라이저가 완료된 후에 만 ​​유효한 (기본값) 값을 갖습니다. 초기화 순서로 인해 인스턴스 생성자가 마지막으로 실행되기 때문에 초기화 프로그램이 실행되는 순간 인스턴스가 생성되지 않습니다. 따라서 컴파일러는 클래스 인스턴스가 완전히 생성되기 전에 인스턴스 속성 (또는 필드)을 참조 할 수 없습니다. 이는 인스턴스 변수에 대한 모든 액세스가 reminder암시 적으로 인스턴스 ( 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 : Class declarations .

즉, 다른 인스턴스 멤버를 참조하여 해당 값을 초기화하는 인스턴스 필드는 인스턴스 생성자에서 초기화하거나 참조 된 멤버를 선언해야합니다 static.


답변