Ошибки PascalABC.NET

Объясните, пожалуйста, есть существенная разница между этим кодом:

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 должна работать понятнее.

Для чего он - знаю, а вот как работает? Может он только в консольных приложениях работу программы прерывает, а в оконных его использовать вообще нельзя? Или я что-то делаю не правильно…

Откройте реализацию assert в PABCSystem. Для этого достаточно написать assert и нажать ПКМ, перейти к реализации(предварительно открыв PABCSystem).

Естественно, в Паскале это реализовано на стандартных .NET библиотеках. Там внутрях вызовы System.Diagnostics.Debug.Assert, как и ожидалось… То есть, надо лезть в офф. документацию. Вообще хотел услышать что-то вроде “assert нужно использовать только так и так, а в этом случае нельзя” или, что это глюк компилятора.

Ну я ж и говорю PABCSystem.assert скорее внутренняя… Она не по каким то стандартам работает а как удобней было бы для тестирования паскаля.

Что такое РазмерКнопок, ОтступОтКнопок? Поля, свойства, методы? В них где-то и падает наверно.

Свою ошибку уже исправил… этот кусок кода в методе, который находился конструкторе. Думал, что при ошибке assert остановит программу, и выведет окошко с сообщением об ошибке. Но он оборвал выполнение не только метода, в котором находился, но и всех внешних. Поэтому экземпляр класса не был создан, и выдало соответствующую ошибку.

Постарайтесь чтобы воспроизводилось. Может, у Вас компьютер с вирусами или антивирусом, который всё гасит, а мы гадать будем

Трудно сказать. Assert - действительно простой вызов функции из .NET-библиотеки. В оконных программах, особенно многопоточных, может работать не так как ожидалось. Я бы пользовался стандартной обработкой исключений

Ну вот на новеньком ноуте этот глюк возник на Вин10 - написал сюда. На счёт антивируса, точно сказать не могу. Каспер ни саму среду не гасит, ни получившиеся программы(в отличие, например, от аваста). Этот глюк у меня появляется редко, но уже был замечен на трёх компах… Постараюсь воспроизвести.

Нужно понять хотя бы, в каких условиях возникает ошибка и что общего между ошибками.

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

А может стоит сделать билд с более подробным дебагом лично для этого случая, чтоб IDE не вылетала, а возвращала точку ошибки?

Вроде бы 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.
([],5)
(nil,0)
(nil,0)
([],5)

Если IDE вылетает, то билды не помогут

Справка -> обобщённые типы -> ограничения на параметры обобщённых подпрограмм и классов: “Можно также использовать присваивание переменной, имеющей тип параметра обобщенного класса или подпрограммы, значение по умолчанию, используя конструкцию default(T) - значение по умолчанию для типа T (nil для ссылочных типов и нулевое значение для размерных типов):”

Нет, значение по умолчанию - это все поля прописываются нулями. Это не C++. В C# вообще запрещено инициализировать поля структур как у нас. Поэтому считайте особенностью реализации.

В таком случае нельзя ли как то сделать перезагрузку default? Нулевое значение не обязательно значит что во всех параметрах нули.

begin
  2**7
end.

Тут всё ясно.
Но не компилятору: () : Встречено ’


Так должно работать?

begin
  2**7.step.Print
end.

" () : Встречено ’ "


А со скобками?

begin
  (2**7).step.Print
end.

" Program1.pas(2) : Неизвестное имя ‘Print’ "


begin
  (2**7).step()
end.

Тут “Program1.pas(2) : Неверное количество параметров функции”, хотя IntelliSense показывает вариант без параметров, так работает:

begin
  (2**7).step(1)
end.

begin
  (2**7).step(1).Print
end.