2013-01-21 11 views
51

Mam klasę i kiedy próbuję użyć jej w innej klasie, otrzymuję błąd poniżej.Inicjator pól nie może odwoływać się do niestatycznego pola, metody ani właściwości

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"); 
     } 

    } 
} 

Korzystanie z klasy do innej klasy

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

Error (CS0236):

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

Dlaczego tak się dzieje i jak to naprawić?

Odpowiedz

75

Linia:

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

Nie można użyć zmiennej instancji w celu zainicjowania innej zmiennej instancji. Czemu? Ponieważ kompilator może je zmienić - nie ma gwarancji, że reminder zostanie zainicjowany przed defaultReminder, więc powyższa linia może rzucić NullReferenceException.

Zamiast tego, po prostu użyć:

private dynamic defaultReminder = TimeSpan.FromMinutes(15); 

Ewentualnie ustawić wartość w konstruktorze:

private dynamic defaultReminder; 

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

Istnieje więcej szczegółów na temat tego błędu kompilatora na MSDN - Compiler Error CS0236.

+2

Java jest bardziej „wyrozumiały” dla tego rodzaju konstrukcji. Nie wiem, czy to dobrze. http://stackoverflow.com/questions/1494735/initialization-order-of-static-fields-in-static-class –

+7

Nie, kompilator nie może zmienić kolejności inicjalizatorów. Specyfikacja języka C# określa w sekcji "10.5.5.2 Inicjalizacja pola instancji" następujące: __ Inicjatory zmiennych są wykonywane w kolejności tekstowej, w której pojawiają się w deklaracji klasy .__ Powtórzono to nawet w "Instancji 10.11.2 inicjatory zmiennych ", gdzie mówią: __ Inicjatory zmiennych są wykonywane w kolejności tekstowej, w której pojawiają się w deklaracji klasy .__ Twoje wyjaśnienie jest błędne. Zamówienie zostało naprawione. Powodem, dla którego jest zabroniony, jest to, że projektanci C# chcieli tego w ten sposób. –

+0

(Tylko w przypadku "klasy częściowej" z "częściami" w kilku plikach jest niejasna kolejność inicjalizacji pól, ale to dotyczy również pól 'statycznych') –

14

Musisz umieścić ten kod do konstruktora klasy:

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

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

Powodem jest to, że nie można używać jednej zmiennej instancji zainicjować kolejną użyciu inicjatora pola, ponieważ kolejność wykonywania inicjatory pól są niezdefiniowane.

+4

Kolejność inicjatorów polowych jest jasno określona! Zobacz mój komentarz do odpowiedzi Odeda. –

3

można użyć jak ten

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

Witamy w Stack Overflow! Chociaż ten fragment kodu może rozwiązać pytanie, w tym [wyjaśnienie] (http://meta.stackexchange.com/q/114762/305455) naprawdę pomaga poprawić jakość twojego postu. Pamiętaj, że odpowiadasz na pytanie przeznaczone dla czytelników w przyszłości, a te osoby mogą nie znać powodów sugestii dotyczących kodu. Proszę również nie tłumić kodu za pomocą komentarzy wyjaśniających, ponieważ zmniejsza to czytelność zarówno kodu, jak i objaśnień! – jmattheis

+1

Używa => zamiast = w ten sposób czyni go właściwością. – wooohoh

Powiązane problemy