Использование неназначенной локальной переменной? C # - PullRequest
3 голосов
/ 03 мая 2011

У меня есть следующий код:

        double ticketPrice;
        LoadOperation loGetTickets = ticketClass.loadTickets();
        loGetTickets.Completed += (s, args) =>
        {
            foreach (Web.Ticket tt in ticketClass.getContext())
            {
                if (tt.bookingId == data.bookingId)
                {
                    pView.lblTicketAmount.Content = "£" + tt.ticketPrice;
                    MessageBox.Show("Price: " + tt.ticketPrice);
                    ticketPrice = Convert.ToDouble(tt.ticketPrice);
                    pView.lblTicketName.Content = tt.ticketName;
                    break;
                }
            }
        }; double subTotal = ticketPrice + ticketQuantity;

Когда я запускаю его, я получаю сообщение об ошибке: Использование неназначенной локальной переменной 'ticketPrice'

Как видите, ему присваивается значение из цикла.

Если я использую:

double ticketPrice = 0.0;

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

Может ли кто-нибудь помочь мне в этом вопросе.

Спасибо

Ответы [ 4 ]

3 голосов
/ 03 мая 2011

Вы говорите, что значение ticketPrice остается нулевым, но код не показывает место, где вы читаете значение переменной!

Такое поведение имело бы смысл, если бы оно использовалось в каком-то коде, который следует за опубликованным вами фрагментом. E.g.:

double ticketPrice;        
LoadOperation loGetTickets = ticketClass.loadTickets();        
loGetTickets.Completed += (s, args) =>  { 
  // Set value of 'ticketPrice'
  ticketPrice = ...
};

// Use the value of the variable
Console.WriteLine(ticketPrice); // (*)

Это не работает, потому что строка, помеченная как (*), на самом деле завершает до , значение переменной устанавливается в обработчике Completed. Чтобы заставить его работать, вам нужно переместить код, который использует переменную, в обработчик (после кода, который устанавливает значение переменной).

Тогда, конечно, не имеет смысла объявлять переменную в методе, потому что она будет использоваться только в теле лямбда-функции, так что вы получите что-то вроде этого:

LoadOperation loGetTickets = ticketClass.loadTickets();        
loGetTickets.Completed += (s, args) =>  { 
  double ticketPrice;        
  // Set value of 'ticketPrice'
  ticketPrice = ...

  // Use the value of the variable
  Console.WriteLine(ticketPrice); // (*)
};

Полагаю, вы только что обнаружили болевую точку асинхронного программирования в C # 4 :-). Вот почему F # поддерживает асинхронные рабочие процессы (где вы можете писать один и тот же код без обработчиков событий) и почему дизайнеры C # думают о том, чтобы добавить подобное в C # в будущем.

1 голос
/ 03 мая 2011

Хотя ticketPrice устанавливается в цикле, он находится внутри обработчика событий. Поскольку это событие имеет возможность никогда не запускаться (что касается компилятора), оно будет обрабатывать его как неназначенное до тех пор, пока оно не наткнется на строку, которая гарантированно будет выполняться.

0 голосов
/ 03 мая 2011

Переменная присваивается, но это происходит позже.

Код для присвоения переменной находится в обработчике событий, поэтому код не запускается до тех пор, пока событие не произойдет, и это после загрузки заявок.

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

0 голосов
/ 03 мая 2011

Переместите оператор double ticketPrive; внутрь foreach, и все будет хорошо.

...