2017-01-26 2 views
3

У меня есть делегатДелегат + = сфера класса оператора против местного масштаба

delegate void Del(int a, int b); 

почему этот код работает:

class MyClass 
{ 
    private Del invoker; 

    public void SetInvoker(Del del) 
    { 
     invoker += del; //everything is ok 
    } 
} 

пока этот код не делает?

public class Program 
    { 
     static void Main(string[] args) 
     { 
      Del invoker += new Del(Display); //error! Invalid expression term '+=' 

     } 

     static void Display(int a, int b) 
     { 

     } 
    } 

это довольно странно, потому что в обоих случаях Вызывающий является нуль перед инициализацией (перед использованием оператора + =)

+0

'частных статических Del Вызывающий;' –

+0

«этот код не» не является полезным описанием проблемы - особенно когда вы должны получать ошибку компилятора, укажите * текст * сообщения об ошибке. –

+0

@Damien_The_Unbeliever Я добавил ошибку – Wachburn

ответ

3

Эта линия

Del invoker += new Del(Display); 

равно

Del invoker; 
invoker = invoker + new Del(Display); 

Если вызывающий абонент не может использоваться в +, потому что он не инициализирован.

Так что

В главном методе ваш invoker является локальным переменным и каждым локальным переменным должны быть инициализирован перед использованием. invoker значение не null, но не не использовался. Если вы не присвоите значение переменной, оно выдает вам error, что оно не инициализируется. Поэтому вам нужно явно назначить null.

public class Program 
{ 
    static void Main(string[] args) 
    { 
     Del invoker = null; 
     invoker += new Del(Display); //error! 
    } 

    static void Display(int a, int b) 
    { 

    } 
} 

При использовании версии class, class'esconstructor инициализирует поля для первого с их значениями по умолчанию. Поэтому после создания объекта все его поля имеют значения по умолчанию, поэтому вы можете использовать += с ними.

+0

Да, вы правы, когда я разделяю инициализацию на две строки, теперь он сообщает правильное сообщение об ошибке: «использование неподписанной локальной переменной». Но если у меня есть одна строка, она говорит «Недопустимый термин выражения» - это путает – Wachburn

+0

@Wachburn с одной строкой, компилятор знает, что он не инициализирован и не понимает следующие операции. Поэтому вам нужно указать ';' –

+0

, возможно, вы хотели сказать: «Где invoker НЕ МОЖЕТ использоваться в операторе +, потому что ...». Кстати, почему вы говорите, что invoker имеет значение null в методе Main? Отладчик показывает, что после объявления установлено значение null. – Wachburn

1

Ну в ошибочного кода, invoker является местного vairable

static void Main(string[] args) 
    { 
     Del invoker += new Del(Display); //error! 

который не initailized и, таким образом, содержит мусор. Вы - , пытающийся добавить Display к мусору, и поэтому это ошибка.

Вы должны инициализировать в invoker, которые вы можете сделать различными способами:

// Fields are initialized by default value; that's why invoker == null 
    private static Del invoker; 

    static void Main(string[] args) 
    { 
     invoker += new Del(Display); 

Или

static void Main(string[] args) 
    { 
     // just an assignment - notice = instead of += 
     Del invoker = new Del(Display); 

Или

static void Main(string[] args) 
    { 
     Del invoker = null; 
     invoker += new Del(Display); 
1

+= просто работает, как и любой другой оператор. Если левый операнд и правый операнд имеют правильные типы, он компилируется.

В первом случае вы добавляете значение Del (параметр) в переменную класса (invoker). Это работает, потому что типы верны.

Но во втором случае:

Del invoker += new Del(Display); //error! 

Посмотрите внимательно на код. Del invoker является переменной декларация. Существует только один оператор, который может быть помещен после объявления переменной, и это =. Ваш код не работает из-за той же причине, почему это не работает:

int a += 10; 

Так использовать = вместо:

Del invoker = new Del(Display); 
+0

Причина, по которой первый пример работает, является конструктором по умолчанию, который устанавливает член invoker для null. Поэтому во втором примере нам также нужно инициализировать invoker с нулем перед использованием оператора + =. – Wachburn

+0

@ Wachburn хм ... это странно. Я попробовал это на csharppad, и это сработало. Во всяком случае, отредактирован. – Sweeper

Смежные вопросы