Объясните, пожалуйста, есть существенная разница между этим кодом:
Case self.Расположение of
33:
Begin
Смещение := ШиринаЭкрана-Ширина-Смещение;
if (Высота+Сдвиг > ВысотаЭкрана) then Высота := ВысотаЭкрана-Сдвиг;
if (Ширина+Смещение > ШиринаЭкрана) then Ширина := ШиринаЭкрана-Смещение;
if (self.КоличествоСтолбцов = 0) then
begin
Assert((РазмерКнопок <> 0)and(ОтступОтКнопок <> 0),'33');
КоличествоСтолбцов := (Ширина-ОтступОтКнопок) div (РазмерКнопок+ОтступОтКнопок);
end;
End;
End;
И этим:
Case self.Расположение of
33:
Begin
Смещение := ШиринаЭкрана-Ширина-Смещение;
if (Высота+Сдвиг > ВысотаЭкрана) then Высота := ВысотаЭкрана-Сдвиг;
if (Ширина+Смещение > ШиринаЭкрана) then Ширина := ШиринаЭкрана-Смещение;
End;
End;
if (self.КоличествоСтолбцов = 0) then
begin
Assert((РазмерКнопок <> 0)and(ОтступОтКнопок <> 0),'33');
КоличествоСтолбцов := (Ширина-ОтступОтКнопок) div (РазмерКнопок+ОтступОтКнопок);
end;
Этот код находится в одном из методов класса.
Первый вариант кода работает, как должен. Разница только в том, что во втором случае, блок if вынесен за пределы case. НО, начинает срабатывать Assert - на пару мгновений - после чего вылетает ошибка “Ошибка времени выполнения: System.NullReferenceException: Ссылка на объект не указывает на экземпляр объекта.”, причём в другом методе этого же класса.
Оказывается, компилятор просто игнорирует создание экземпляра класса и следующие за ним задания значений свойств, и происходит это уже в другом месте. Отладчик доходит до этого места и просто пролетает его, и всё что следует после.
Нашёл с утра по раньше ошибку у себя. Возник другой вопрос, как работает assert? Он вроде должен останавливать работу программы, а вместо этого программа продолжает работать и отладка прерывается.
assert используется в программах для тестирования паскаля, чтоб когда разработчики добавляют фичу - проверить не сломала ли она что то.
Вот к примеру, это вроде последний добавленный такой файл. System.Diagnostics.Debug.Assert должна работать понятнее.
Для чего он - знаю, а вот как работает? Может он только в консольных приложениях работу программы прерывает, а в оконных его использовать вообще нельзя? Или я что-то делаю не правильно…
Естественно, в Паскале это реализовано на стандартных .NET библиотеках. Там внутрях вызовы System.Diagnostics.Debug.Assert, как и ожидалось… То есть, надо лезть в офф. документацию. Вообще хотел услышать что-то вроде “assert нужно использовать только так и так, а в этом случае нельзя” или, что это глюк компилятора.
Свою ошибку уже исправил… этот кусок кода в методе, который находился конструкторе. Думал, что при ошибке assert остановит программу, и выведет окошко с сообщением об ошибке. Но он оборвал выполнение не только метода, в котором находился, но и всех внешних. Поэтому экземпляр класса не был создан, и выдало соответствующую ошибку.
Трудно сказать. Assert - действительно простой вызов функции из .NET-библиотеки. В оконных программах, особенно многопоточных, может работать не так как ожидалось. Я бы пользовался стандартной обработкой исключений
Ну вот на новеньком ноуте этот глюк возник на Вин10 - написал сюда. На счёт антивируса, точно сказать не могу. Каспер ни саму среду не гасит, ни получившиеся программы(в отличие, например, от аваста). Этот глюк у меня появляется редко, но уже был замечен на трёх компах… Постараюсь воспроизвести.
Поначалу мне казалось, что это ошибка с IntelliSense - когда компилятор падает после нажатия точки - но, помнится, были случаи и без точки падал(хотя приведённый пример как раз такой). По-моему, это два разных глюка, и конкретно этот возникает исключительно после ошибки компиляции.
Вроде бы default(имя_записи) должно давать переменную заполненную значениями по умолчанию, но им даёт нулевые значения вместо этого, это ошибка?
type
t1=class
public a := new byte[0];
public b := 5;
end;
t2=record
public a := new byte[0];
public b := 5;
end;
begin
writeln(new t1);
writeln(new t2);
writeln(default(t2));
var a:t2;
writeln(a);
end.
Справка -> обобщённые типы -> ограничения на параметры обобщённых подпрограмм и классов:
“Можно также использовать присваивание переменной, имеющей тип параметра обобщенного класса или подпрограммы, значение по умолчанию, используя конструкцию default(T) - значение по умолчанию для типа T (nil для ссылочных типов и нулевое значение для размерных типов):”
Нет, значение по умолчанию - это все поля прописываются нулями. Это не C++. В C# вообще запрещено инициализировать поля структур как у нас. Поэтому считайте особенностью реализации.