【问题标题】:C# static scope issueC# 静态范围问题
【发布时间】:2011-07-07 07:53:47
【问题描述】:

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

【问题讨论】:

    标签: c# wpf oop scope downloadstring


    【解决方案1】:

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

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

    【讨论】:

      【解决方案2】:

      我知道这是因为 函数 DownloadCompletedCallback 是 声明为静态,但我没有 了解为什么这很重要。

      来自 C# 规范:

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

      实例方法 在特定实例上运行,并且 可以访问静态和实例 成员。一个实例 实例方法被调用可以是 像这样显式访问。它是一个 在静态中引用此错误 方法。

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

      禁止的例子:

      Class Example{...}
      
      var ExampleOne = new Example();
      var ExampleTwo = new Example();
      
      Example.CallStaticMethod();
      

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

      【讨论】:

      • 由于某种原因昨晚深夜,我认为 DownloadCompletedCallback 必须是静态的。事实证明,没有一个函数必须如此,它可以通过删除所有静态声明来工作。但是,这个答案帮助我比我更好地理解了静态函数。谢谢。
      【解决方案3】:

      这很重要,因为在此类的不同实例中可能有许多不同的lblDebugs。您的函数未绑定到任何特定实例(因为您将其声明为 static),因此代码无法猜测您指的是哪个 lblDebug

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

      【讨论】:

        【解决方案4】:

        您不能在 static 方法中使用 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);
        

        【讨论】:

          【解决方案5】:

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

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2019-05-27
            • 1970-01-01
            • 2011-01-08
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2010-10-11
            • 1970-01-01
            相关资源
            最近更新 更多