3

使用 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;
    }
}
4

5 回答 5

3

我知道这是因为函数 DownloadCompletedCallback 被声明为静态,但我不明白为什么这很重要。

从 C# 规范:

使用 static 修饰符声明的方法是静态方法。静态方法不对特定实例进行操作,只能直接访问静态成员。没有静态修饰符声明的方法是实例方法。

实例方法对特定实例进行操作,并且可以访问静态成员和实例成员。调用实例方法的实例可以显式访问 this。在静态方法中引用 this 是错误的。

这是因为静态方法不是对象的一部分,所以它们不能与任何对象交互。它们与没有状态概念的类相关联,因此当您调用它时,静态方法不知道它应该与哪个对象交互的非静态对象变量。

禁止的示例:

Class Example{...}

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

Example.CallStaticMethod();

所以现在问题变成了它应该与哪些非静态变量交互?它应该是ExampleOneor ExampleTwo,还是应该只是抛出一个空引用异常。在前两种情况下,系统无法知道它应该与哪个交互,因为您从未指定它(或者它是一个实例方法)。第三,它不是真正静态的,因为您需要有一个实例来调用它。所以必须禁止访问非静态方法属性等,因为有太多的歧义。

于 2011-03-02T14:26:57.810 回答
2

静态方法存在于级别,不知道任何特定的用户控件实例。您的所有标签等都在您的用户控件类的特定实例上声明;在你的应用程序的不同地方可能有许多声明。静态方法存在于用户控件的所有此类实例中。

例如,如果你有 5 个用户控件存在于不同的地方,它们共享相同的静态方法,并且该方法无法访问恰好调用它的特定实例。

于 2011-03-02T14:26:18.153 回答
0

lblDebug这很重要,因为此类的不同实例中可能有许多不同的 s。您的函数未绑定到任何特定实例(因为您声明了它static),因此代码无法猜测lblDebug您的意思。

如果你只想要一个lblDebug,你也可以声明它 static - 但在你这样做之前要仔细考虑这意味着什么!

于 2011-03-02T14:27:52.520 回答
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);
于 2011-03-02T14:32:37.777 回答
0

我认为这也是因为您无法访问 lblDebug 因为它在另一个线程上。(DownloadCompletedCallback 是异步的,所以它在另一个线程上执行)。您需要使用来自其父级的调度程序对象调用 lblDebug。不过,您将不得不搜索调用,我这里没有用于确切代码的视觉工作室。

于 2011-03-02T14:35:42.083 回答