2013-01-21 14 views
51

Ho una classe e quando provo ad usarlo in un'altra classe, ricevo l'errore seguente.Un inizializzatore di campo non può fare riferimento al campo, metodo o proprietà non statica

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

    } 
} 

Uso della classe in un'altra classe

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 

Perché accade e come risolvere il problema?

risposta

75

Questa linea:

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

Non è possibile utilizzare una variabile di istanza per inizializzare un'altra variabile esempio. Perché? Perché il compilatore può riorganizzare questi - non è garantito che reminder verrà inizializzato prima di defaultReminder, pertanto la riga precedente potrebbe inviare un NullReferenceException.

Invece, basta usare:

private dynamic defaultReminder = TimeSpan.FromMinutes(15); 

In alternativa, impostare il valore nel costruttore:

private dynamic defaultReminder; 

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

Non ci sono ulteriori dettagli su questo errore di compilazione su MSDN - Compiler Error CS0236.

+2

Java è più 'perdono' per questo tipo di costrutti. Non so se sia una buona cosa. http://stackoverflow.com/questions/1494735/initialization-order-of-static-fields-in-static-class –

+7

No, il compilatore non può riorganizzare gli inizializzatori. Gli stati della specifica della lingua C#, nella sezione "Inizializzazione del campo Istanza 10.5.5.2", sono i seguenti: __L'inizializzazione delle variabili viene eseguita nell'ordine testuale in cui compaiono nella dichiarazione della classe .__ Ciò viene ripetuto anche in "Istanza 10.11.2" inizializzatori variabili "dove dicono: __I inizializzatori variabili vengono eseguiti nell'ordine testuale in cui appaiono nella dichiarazione della classe .__ Quindi la tua spiegazione è sbagliata. L'ordine è fisso. Il motivo per cui non è consentito è che i progettisti di C# lo volessero in quel modo. –

+0

(Solo nel caso di una 'classe parziale' con" parti "in diversi file l'ordine degli inizializzatori di campo non è chiaro, ma vale anche per i campi' static'!) –

14

è necessario mettere il codice nel costruttore della classe:

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

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

La ragione è che non è possibile utilizzare una variabile di istanza per inizializzare un altro utilizzando un inizializzatore campo, perché l'ordine di esecuzione di il campo inizializzatori non è definito.

+4

L'ordine degli inizializzatori di campo è chiaramente definito! Vedi il mio commento alla risposta di Oded. –

3

è possibile utilizzare come questo

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

Benvenuti in Stack Overflow! Sebbene questo snippet di codice possa risolvere la domanda, inclusa una [spiegazione] (http://meta.stackexchange.com/q/114762/305455) aiuta davvero a migliorare la qualità del tuo post. Ricorda che stai rispondendo alla domanda per i lettori in futuro, e queste persone potrebbero non conoscere le ragioni del tuo suggerimento sul codice. Cerca anche di non affollare il tuo codice con commenti esplicativi, in quanto ciò riduce la leggibilità sia del codice che delle spiegazioni! – jmattheis

+1

Sta usando => invece di = rendendola così una proprietà. – wooohoh

Problemi correlati