2013-01-21 29 views
51

我有一個類,當我嘗試在另一個類中使用它時,我收到下面的錯誤。字段初始值設定項不能引用非靜態字段,方法或屬性

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 

它爲什麼會發生,以及如何解決它?

回答

75

這條線:

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

+2

Java是這幾樣結構的更「寬容」。不知道這是否是件好事。 http://stackoverflow.com/questions/1494735/initialization-order-of-static-fields-in-static-class –

+7

不,編譯器不能重新排列初始值設定項。 C#語言規範在「10.5.5.2實例字段初始化」一節中聲明如下:__變量初始值設定項按它們出現在類聲明中的文本順序執行.__甚至在「10.11.2實例變量初始值設定項「他們說:__變量初始值設定項是按它們出現在類聲明中的文本順序執行的。所以你的解釋是錯誤的。訂單是固定的。之所以被禁止是因爲C#的設計者就是這麼想的。 –

+0

(只有在幾個文件中帶有「部分」的「partial class」的情況下,字段初始值設定項的順序不清楚,但也適用於'static'字段!) –

14

你需要把這些代碼到你的類的構造函數:

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

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

的原因是,你不能用一個實例變量初始化使用領域初始化一個又一個,因爲執行順序字段初始值未定義。

+4

字段初始值設定項的順序是明確定義的!看到我的評論Oded的答案。 –

3

你可以使用這樣

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

歡迎來到堆棧溢出!雖然此代碼片段可能會解決此問題,但包括[解釋](http://meta.stackexchange.com/q/114762/305455)確實有助於提高帖子的質量。請記住,您將來會爲讀者回答問題,而這些人可能不知道您的代碼建議的原因。也請儘量不要使用解釋性註釋來擠佔代碼,因爲這會降低代碼和解釋的可讀性! – jmattheis

+1

它使用=>而不是=因此使它成爲一個屬性。 – wooohoh

相關問題