Автосвойства

Предлагаю вернутся к этой теме, и всё же обсудить - как это может быть реализовано.

Моё предложение состоит в том чтоб сделать описание возможности записи и чтения как у интерфейсов:

Unit1:

unit Unit1;

type
  t1 = class
    auto property Prop1: integer read write;
    auto property Prop2: integer read;
    
    procedure p1;
    begin
      //внутри класса можно и читать и перезаписывать все авто свойства,
      //потому что в данном случае идёт обращение к внутреннему приватному полю,
      //а к ним можно обращатся из любой части класса
      Prop1 += 1;
      Prop2 += 1;
    end;
  end;

begin
  var a := new t1;
  
  a.Prop1 += 1;//тут есть оба, и read и write, поэтому можно
  
  a.Prop2 += 1;//тут вроде тоже можно, из затого что приватные поля видно из всего поля
               //но это уже спорный момент
  
end.

Основная программа:

uses Unit1;

begin
  var a := new t1;
  
  a.Prop1 += 1;//Тут есть оба, и read и write, поэтому можно
  
  a.Prop2.Print;//Читать можно
  a.Prop2 := 1;//А вот записывать уже нельзя
  
end.

Unit1 будет разворачиваться в:

unit Unit1;

type
  t1 = class
    private $Prop1:integer;
    private $Prop2:integer;
    
    internal property Prop1: integer read $Prop1 write $Prop1;
    internal property Prop2: integer read $Prop2;
    
    internal procedure p1;
    begin
      $Prop1 += 1;
      $Prop2 += 1;
    end;
  end;

begin
  var a := new t1;
  
  {
  //стоит ли разрешать?
  a.$Prop1 += 1;
  a.$Prop2 += 1;
  {}
  //(вариант если НЕ разрешать)
  a.Prop1 += 1;
  //a.Prop2 += 1;//не откомпилируется
  {}
  
end.

Кто что думает о таком синтаксисе? У кого есть другие идеи? Давайте писать сюда.

Правильно ли я понимаю, что автосвойства отличаются от полей лишь возможностью задать уровень доступа read?

Если смотреть с этой стороны - да, относительно полей это единственное отличие.

Но как @VladislavMoldovan правильно подметил в #844 - в .Net очень редко оставляют публичные поля. Даже если подключившему библиотеку можно и читать и записывать их - их всё равно оборачивают в свойство.

1 лайк

Расскажите мне, зачем. Слова “так делают” меня не убеждают.

1 лайк

Отсюда я прочитал что основное преимущество - это возможность не ломать библиотеку, если понадобится в будущих версиях поставить какую то логику на запись или чтение свойства. То есть, вот был тип в библиотеке:

  t1=class
    public data1:real;
  end;

Кто то пользовался этой библиотекой, создал свой .exe на её основе. Теперь, нам вдруг понадобилось выписывать data1 когда его перезаписывают:

  t1=class
    private _data1:real;
    
    public property data1:real read _data1 write
    begin
      _data1 := value;
      writeln(_data1);
    end;
  end;

Теперь, если обновить до этой версии .dll, не обновив .exe - .exe сломается. А если бы data1 было свойством с самого начала - ничего бы не сломалось.

Так же там было про то что для полей не работает Remoting, доступ через System.Reflection и data binding, но за то что правильно понял эту часть я ручиться не могу.

1 лайк

Ну, я всё это более-менее знаю. Не впечатляет если честно. Reflection для полей несомненно работает. Стандартный binding там конечно - основное. Но он приличным образом делается только в xml - вна голом C# надо написать тьму кода.

exe будут не работать с новыми dll без перекомпиляции по огромному количеству причин - это всего лишь одна из многих. Поэтому лучше exe всё же перекомпилировать тоже.

Извиняюсь, что спустя месяц, но

Это затем, чтобы не нарушать логику. Допустим, имеем класс:

Type Layer = Sealed Class
  Public InputWidth: Int32;
  Public InputHeight: Int32;
  Public InputDepth: Int32;
  Public OutputWidth: Int32;
  Public OutputHeight: Int32;
  Public OutputDepth: Int32;
  Public Constructor Create();
  Begin
  End;
End;

Выглядит привычно. Поля класса. Но вот если посмотреть извне, то получается, что размеры входа и выхода - просто данные слоя(так как выглядят полями). А на самом деле - это именно свойства слоя, но они ведь должны где-то лежать. На практике - да, это имеет мало смысла, но вот интерфейс класса или структуры они способны значительно улучшить. У открытых полей своё назначение. А если так делают, то не “просто так, чтобы было”. Не дураки ведь. Сам поначалу не видел в этом смысла, но как дошло до реализации больших классов внутри dll, моё мнение поспешило измениться(само :smile: ).

1 лайк

На какой стадии разработки автосвойства?

1 лайк

А за них вообще взялись? Там какая - то неопределённость была.

Не знаю. Вот и спросил.

Глеб, объедините темы

@Admin, на какой стадии разработки автосвойства? Планируется ли их внедрять в скором будущем в PascalABC.Net или их реализация откладывается на более длительный срок? Хотелось бы услышать Ваши планы на это счёт (если они имеются, разумеется).

Я вот вспоминаю, где была мотивировка их введения. Если найдёте ссылку - хорошо. Без мотивировки делать не хочется

Ну, как минимум их можно делать только читаемыми вне модуля, с полями вы отказались так делать. А так - там полно мелких причин, как совместимость версий библиотек (можно заменить авто свойство на обычное свойство, без потери совместимости), или того, что на .Net не принято делать публичные поля классам, всё публичное должно быть свойствами.

1 лайк

Ещё как вариант - ускорение перевода из C# в PascalABC.NET.

Это положительный побочный эффект внедрения автосвойств.

А как их сделать только читаемыми вне модуля? Я так понимаю, что вы хотите модификаторы get; private set. Но так усложнять язык мы несомненно не будем.

Если это - всего лишь побочный эффект, то каково основное действие?! :smile:

А какой в этом смысл, просветите? И почему обязательно модуль?

мутная какая-то фича. свойства ради свойств.

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

Вот как раз чтоб не усложнять язык - пусть так работает, то есть полностью отражает по функционалу как если было бы приватное поле+свойство. Но чтоб при этом записывалось по другому.