2011-03-02 44 views
3

使用WPF和.NET 4.0。C#靜態作用域問題

我正在使用WebClient下載一些數據並使用DownloadStringCompletedEventHandler在完成時觸發我的DownloadCompletedCallback功能。

我遇到的問題是,當DownloadCompletedCallback被調用時,我試圖在主窗體上設置標籤的內容並顯示錯誤。

非靜態字段,方法或屬性'Armory.MainWindow.lblDebug'需要對象引用。

據我所知,這是因爲函數DownloadCompletedCallback被聲明爲靜態,但我不明白爲什麼這很重要。

這是我正在使用的代碼。

public static void DownloadHTML(string address) 
{ 
    WebClient client = new WebClient(); 

    client.DownloadStringCompleted += new DownloadStringCompletedEventHandler(DownloadCompletedCallback); 

    client.DownloadStringAsync(new Uri(address)); 
} 

private static void DownloadCompletedCallback(Object sender, DownloadStringCompletedEventArgs e) 
{ 
    if (!e.Cancelled && e.Error == null) 
    { 
     lblDebug.Content = (string)e.Result; 
    } 
} 

回答

3

我所知,這是因爲 功能DownloadCompletedCallback聲明爲static 但我不 明白爲什麼這很重要。

從C#規格:

具有靜態 修飾符聲明的方法是一個靜態方法。靜態 方法不能在特定的 實例上運行,並且只能直接訪問 靜態成員。沒有靜態修飾符的聲明爲 的方法是 實例方法。

實例方法 在特定實例上運行, 可以同時訪問靜態和實例 成員。調用實例方法的實例可以是 ,因爲這樣可以顯式訪問實例方法。在靜態 方法中引用此錯誤是 錯誤。

這是因爲靜態方法不是對象的一部分,所以它們不能與任何對象交互。它們綁定到沒有狀態概念的類,所以當你調用它時,靜態方法不知道應該與哪個非靜態對象變量交互。

爲什麼它是被禁止的例子:

Class Example{...} 

var ExampleOne = new Example(); 
var ExampleTwo = new Example(); 

Example.CallStaticMethod(); 

所以,現在的問題是哪些非靜態變量它與互動?應該是ExampleOne還是ExampleTwo,還是應該拋出一個空引用異常。在前兩種情況下,系統無法知道應該與哪個應用交互,因爲您從未指定過它(或者它是實例方法)。第三,它不是真正的靜態,因爲你需要有一個實例來調用它。因此,禁止訪問非靜態方法屬性等,因爲不太明確。

+0

由於某種原因,昨晚深夜,我一直認爲DownloadCompletedCallback必須是靜態的。原來,沒有一個函數必須是這樣的,它通過移除所有靜態聲明來工作。但是,這個答案幫助我理解靜態函數的方式比我更好。謝謝。 – castis 2011-03-02 14:57:41

2

靜態方法在水平存在,並沒有任何特定的用戶控件實例的知識。所有的標籤等都是在用戶控件類的特定實例上聲明的;在你的應用程序的不同地方可能會有很多聲明。所有這些用戶控件實例都存在靜態方法。

如果你有5個用戶控件存在於不同的地方,所有他們共享相同的靜態方法,並且該方法無法訪問恰好恰好調用它的特定實例。

0

這很重要,因爲在此類的不同實例中可能會有許多不同的lblDebug。你的函數沒有綁定到任何特定的實例(因爲你聲明它是static),所以代碼無法猜出你的意思。

如果你只想要一個lblDebug,你也可以聲明這個靜態的 - 但仔細想想在你這樣做之前這將意味着什麼!

0

您無法使用lblDebug in static方法。使用

public static void DownloadHTML(
    string address, 
    DownloadStringCompletedEventHandler callWhenCompleted) 
{ 
    WebClient client = new WebClient(); 

    client.DownloadStringCompleted += 
     new DownloadStringCompletedEventHandler(callWhenCompleted); 

    client.DownloadStringAsync(new Uri(address)); 
} 

private void DownloadCompletedCallback(
    Object sender, DownloadStringCompletedEventArgs e) 
{ 
    if (!e.Cancelled && e.Error == null) 
    { 
     lblDebug.Content = (string)e.Result; 
    } 
} 

:相反,你可以改變DownloadHTML方法接受一個回調

DownloadHTML(
    "http://stackoverflow.com/questions/5168788/c-static-scope-issue", 
    this.DownloadCompletedCallback); 
0

我認爲這也是因爲,因爲它是在另一個線程你不能訪問lblDebug。 (DownloadCompletedCallback是異步的,所以它在另一個線程上執行)。你需要調用lblDebug和一個來自父級的調度對象。你將不得不搜索調用,但我沒有一個視覺工作室在這裏確切的代碼。