使用WPF和.NET 4.0。
我正在使用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;
}
}
答案 0 :(得分:3)
我明白这是因为 函数DownloadCompletedCallback是 声明为静态,但我没有 明白为什么这很重要。
来自C#规范:
用静态声明的方法 修饰符是一种静态方法。静止的 方法不适用于特定的 实例并且只能直接访问 静态成员。声明了一个方法 没有静态修饰符是一个 实例方法。
实例方法 在特定的实例上运行 可以访问静态和实例 成员。一个实例 调用实例方法即可 显式访问为此。它是一个 在静态中引用此错误 方法
这是因为静态方法不是对象的一部分,所以它们不能与任何东西进行交互。它们与没有状态概念的类相关联,所以当你调用它时,静态方法不知道它应该与哪个对象进行交互的非静态对象变量。
禁止这样做的一个例子:
Class Example{...}
var ExampleOne = new Example();
var ExampleTwo = new Example();
Example.CallStaticMethod();
现在问题是它应该与哪些非静态变量进行交互?应该是ExampleOne
还是ExampleTwo
,还是应该抛出空引用异常。在前两种情况下,系统无法知道它应与之交互,因为您从未指定它(或者它是实例方法)。对于第三个,它不是真正的静态,因为你需要有一个实例来调用它。因此,必须禁止访问非静态方法属性等,因为存在太多歧义。
答案 1 :(得分:2)
静态方法存在于类级别,并且不知道任何特定的用户控件实例。所有标签等都在用户控件类的特定实例上声明;在你的应用程序中,可能会有许多声明在各个地方声明。所有此类用户控件实例都存在静态方法。
如果你有5个用户控件存在于不同的地方,所有它们共享相同的静态方法,并且该方法无法访问恰好调用它的特定实例
答案 2 :(得分:0)
这很重要,因为在这个类的不同实例中可能有许多不同的lblDebug
。您的函数与任何特定实例无关(因为您声明了它static
),因此代码无法猜出您的lblDebug
是什么意思。
如果你只需要一个lblDebug
,你也可以声明那个静态 - 但在你这样做之前要仔细考虑这意味着什么!
答案 3 :(得分:0)
您无法在静态方法中使用 lblDebug 。相反,您可以更改DownloadHTML方法以接受回调:
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(
"http://stackoverflow.com/questions/5168788/c-static-scope-issue",
this.DownloadCompletedCallback);
答案 4 :(得分:0)
我认为这也是因为你无法访问lblDebug,因为它在另一个线程上。 (DownloadCompletedCallback是异步的,因此它在另一个线程上执行)。您需要使用其父级的调度程序对象调用lblDebug。你将不得不搜索调用,我没有这里的视觉工作室的确切代码。