3

Using WPF and .NET 4.0.

I'm downloading some data using WebClient and using DownloadStringCompletedEventHandler to fire off my DownloadCompletedCallback function upon completion.

The issue I'm having is that when DownloadCompletedCallback is called I'm trying to set the contents of a label on the main form and am presented with the error.

An object reference is required for the non-static field, method, or property 'Armory.MainWindow.lblDebug'.

I understand that it's because the function DownloadCompletedCallback is declared as static but I don't understand why that matters.

Here's the code I'm using.

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;
    }
}
Antoine Aubry
  • 12,203
  • 10
  • 45
  • 74
castis
  • 8,154
  • 4
  • 41
  • 63

5 Answers5

3

I understand that it's because the function DownloadCompletedCallback is declared as static but I don't understand why that matters.

From the C# specification:

A method declared with a static modifier is a static method. A static method does not operate on a specific instance and can only directly access static members. A method declared without a static modifier is an instance method.

An instance method operates on a specific instance and can access both static and instance members. The instance on which an instance method was invoked can be explicitly accessed as this. It is an error to refer to this in a static method.

It is because static methods aren't part of the object, so they can't interact with anything that is. They are tied to the class which has no concept of state, so when you call it, the static method has no idea which object the non-static object variables it should interact with.

An example why it's forbidden:

Class Example{...}

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

Example.CallStaticMethod();

So now the question becomes which non static variables should it interact with? Should it be ExampleOne or ExampleTwo, or should it just throw an null reference exception. In the first two cases there is no way for the system to know which it should interact with, because you never specified it (or it'd be an instance method). For the third, it's not really static since you'd need to have an instance to call it. So accessing non-static methods properties etc. has to be forbidden, because there is too much ambiguity not to.

Community
  • 1
  • 1
kemiller2002
  • 113,795
  • 27
  • 197
  • 251
  • For some reason late last night, I was thinking that the DownloadCompletedCallback had to be static. Turns out, none of the functions have to be so it works by removing all the static declarations. However, this answer helped me understand static functions way better than I did. Thank you. – castis Mar 02 '11 at 14:57
2

Static methods exist at the class level, and have no knowledge of any specific user control instance. All of your labels and such are declared on a specific instance of your user control class; there could be many of them declared in various places in your application. A static method exists across all such instances of your user control.

If you have, say, 5 user controls existing in various places, all of them share the same static method, and the method has no way of accessing the specific instance that just happened to call it.

Adam Rackis
  • 82,527
  • 56
  • 270
  • 393
0

It matters because there could be many different lblDebugs in different instances of this class. Your function is not tied to any particular instance (because you declared it static), so the code cannot guess which lblDebug you mean.

If you only want a single lblDebug, you could declare that static as well - but think carefully about what this would mean before you do so!

Riley Lark
  • 20,660
  • 15
  • 80
  • 128
0

You couldn't use lblDebug in static method. Instead, you can change DownloadHTML method to accept a callback:

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

Using:

DownloadHTML(
     "http://stackoverflow.com/questions/5168788/c-static-scope-issue",
     this.DownloadCompletedCallback);
Sergio Rykov
  • 4,176
  • 25
  • 23
0

I think it's also because you can't access lblDebug because it's on another thread. (DownloadCompletedCallback is async, so it's executed on another thread). You need to invoke lblDebug with a dispatcher object from its parent. You're going to have to search for invoking though, i don't have a visual studio here for the exact code.

hcb
  • 8,147
  • 1
  • 18
  • 17