Сегодня написал метод, который выглядел примерно так:
public methodName(int id) { int i = id + 1; ... ... }
Компилирую и вижу вот такое сообщение об ошибке от компилятора: Source.cs:869 - Cannot use local variable 'id' before it is declared. Сижу, смотрю на ошибку и думаю, толи я идиот, то ли компилятор C# сегодня решил повыделываться. Вот же оно объявление переменной, которая передается в метод и тут же я его использую. С какого перепуга он мне говорит, что он не видит объявления?
Я минут пять не верил своим глазам, смотрел на ошибку и смотрел на код, но не могу понять, где же я лохонулся. Решил сделать вот такой вот финт:
public methodName(int id) { int id; int i = id + 1; ... ... }
На этот раз получаю вполне логичную ошибку: A local variable named 'id' cannot be declared in this scope because it would give a different meaning to 'id', which is already used in a 'parent or current' scope to denote something else. И тут я вижу, что у меня такая ошибка не одна, а две в разнях строках.
Я показал только набросок метода, который я накатал, но на самом деле он был размером с 30 строк и ошибок было 5. Я же обратил внимание только на первую и вторую. Во второй была банальная опечатка The name 'notee' does not exist in the current context. Реальная ошибка была почти в конце метода:
public methodName(int id) { int i = id + 1; ... ... int id = InsertToDB(); ... }
Компилятор почему-то проругался на первую строку, хотя она вполне легальна. Некорректна строка со вторым объявлением переменной id. Но это объявление почему-то снесло крышу компилятору и он стал ругаться на первое объявление. В принципе, косяк действительно был в моем коде, просто впервые вижу, чтобы первая ошибка была следствием последней. В основном компилятор показывает все последовательно и логично и можно последовательно латать свои баги.
Понравилось? Кликни Лайк, чтобы я знал, какой контент более интересен читателям. Заметку пока еще никто не лайкал и ты можешь быть первым
По моему в Delphi всегда так: одна какая то ошибка, а компилятор показывает штук по несколько в разных местах. Исправляем одну и остальные пропадают сами.
Это нормальная ситуация, когда первая ошибка является причиной для второй, третьей и даже 10-й ошибки. Код анализируется последовательно, и по умолчанию не останавливается на первой найденой ошибке. Такое я вижу часто. Но чтобы 4-я ошибка была причиной первой, вижу впервые. На мой взгляд, немного не логично.
Не поленился, набрал код. Все логично, компилятор выделяет 1-ю строку кода и пишет, что невозможно использовать локальную переменную до её объявления. Что не логичного??? Если ты объявляешь её ниже.
Не логично, потому что у тебя есть параметр с таким именем и компилятор должен видеть эту переменную в параметре. Логичной является ошибка A local variable named 'id' cannot be declared in this scope because it would give a different meaning to 'id', потому что именно она вызывает проблему.
Все дело в том, что современные компиляторы взяли за правило компилировать код не останавливаясь на возможных ошибках. То есть, сперва компилируем всё и выводим все найденные ошибки. Это возможно сделать только если за первый проход компилятора ошибки определялись синтаксическим анализатором компилятора и записывались в массив или список. Давайте просмотрим что при таком подходе происходит.
Итак строка:
methodName(int id)
допустим, что (утрировано) переменные и их типы мы храним в списке List[Name]=Type и в этой строке список преобретает такое значение List[id]=int, ну то есть в список мы записываем имя переменной и её тип.
Далее анализатор натыкается на данную строку
int id = InsertToDB();
Естественно если он не может определить тип какой то переменной, то, что бы продолжить компилирование он должен присвоить тип и значение по умолчанию данной переменной. В итоге имеем следующее:
List[InsertToDB]=Unknown
или другой тип отличный от int и, что бы не допустить ошибки при дальнейшей компиляции необходима замена
List[id]=int на List[id]=Unknown так как язык является строго типизированым и типы должны совпадать. Уж почему в этом случае тип по умолчанию берётся неопределённый остаётся спросить разработчиков?
И напоследок, при втором проходе сравниваются типы переменных и получается, что в строке
int i = id + 1;
id имеет тип Unknown о чем и сообщает компилятор.
Я вообще к таким выкрутасам мысли разработчиков отношусь не одобрительно, так как это вводит программиста в заблуждение, что может привести к трудностям восприятия своего же кода, как и произошло с вами Михаил.
Прекрасно понимаю, почему это произошло. Просто локальная переменная объявленная внутри метода,имеет приоритет над переменными класса. Если у тебя есть что-то типа:
Хотите найти еще что-то интересное почитать? Можно попробовать отфильтровать заметки на блоге по категориям.