C # статическая проблема области - PullRequest
3 голосов
/ 02 марта 2011

Использование 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;
    }
}

Ответы [ 5 ]

3 голосов
/ 02 марта 2011

Я понимаю, что это потому, что функция DownloadCompletedCallback объявлена ​​как статическая, но я не понимаю, почему это важно.

Из спецификации C #:

Метод, объявленный со статическим модификатором, является статическим методом.Статический метод не работает с конкретным экземпляром и может напрямую обращаться только к статическим элементам.Метод, объявленный без статического модификатора, является методом экземпляра.

Метод экземпляра работает с конкретным экземпляром и может обращаться как к статическим, так и к членам экземпляра.К экземпляру, для которого был вызван метод экземпляра, можно получить явный доступ как этот.Ошибочно ссылаться на это в статическом методе.

Это потому, что статические методы не являются частью объекта, поэтому они не могут взаимодействовать с чем-либо, что есть.Они привязаны к классу, который не имеет понятия состояния, поэтому при его вызове статический метод не имеет представления, с каким объектом должны взаимодействовать нестатические переменные объекта.

Пример, почему это запрещено:

Class Example{...}

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

Example.CallStaticMethod();

Итак, теперь возникает вопрос, с какими нестатическими переменными он должен взаимодействовать?Должно ли это быть ExampleOne или ExampleTwo, или просто выдать исключение нулевой ссылки.В первых двух случаях у системы нет возможности узнать, с чем она должна взаимодействовать, потому что вы никогда не указывали ее (или это был бы метод экземпляра).В-третьих, это не совсем статично, так как вам нужен экземпляр для его вызова.Поэтому доступ к свойствам нестатических методов и т. Д. Должен быть запрещен, потому что слишком много двусмысленности, чтобы этого не делать.

2 голосов
/ 02 марта 2011

Статические методы существуют на уровне class и не знают ни одного конкретного экземпляра пользовательского элемента управления. Все ваши метки и тому подобное объявлены в конкретном экземпляре вашего класса управления пользователем; в вашем приложении их может быть много, объявленных в разных местах. Статический метод существует во всех таких экземплярах вашего пользовательского элемента управления.

Если, скажем, у вас есть 5 пользовательских элементов управления, существующих в разных местах, все из них используют один и тот же статический метод, и у метода нет способа получить доступ к конкретному экземпляру, который только что вызвал его.

0 голосов
/ 02 марта 2011

Я думаю, это также потому, что вы не можете получить доступ к lblDebug, потому что он находится в другом потоке. (DownloadCompletedCallback является асинхронным, поэтому выполняется в другом потоке). Вам нужно вызвать lblDebug с объектом диспетчера от его родителя. Вам придется искать вызов, хотя у меня нет визуальной студии для точного кода.

0 голосов
/ 02 марта 2011

Вы не можете использовать 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(
     "/7068782/c-staticheskaya-problema-oblasti",
     this.DownloadCompletedCallback);
0 голосов
/ 02 марта 2011

Это важно, потому что может быть много разных lblDebug в разных экземплярах этого класса.Ваша функция не привязана к какому-либо конкретному экземпляру (потому что вы объявили его static), поэтому код не может угадать, какой lblDebug вы имеете в виду.

Если вам нужен только один lblDebug, вы можете объявитьэто тоже статично - но подумайте, что бы это значило, прежде чем делать это!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...