Конференция "Основная" » о дженериках
 
  • maxsvt © (08.08.16 02:45) [0]
    Привет всем. Пользуетесь ли часто дженериками в разработке приложений? Не так давно захотел переделать часть проекта с использованием дженериков, ну типа модно, удобно и все такое :)
    В плане создания простых рекордов и методов классов, без использования конвертирования в реальные типы - получается действительно интересно. Но вот если в методе приходится конвертировать и много дженерики в реальные типы (в том числе и внутренние переменные класса), выходит совсем неудобочитаемый код, хотя, дженерики вроде как подразумевались для упрощения жизни. Что бы было понятнее, приведу простой абстрактный пример. Есть класс и функция, которая в зависимости от типа создаваемого обьекта конвертирует параметр в строку


    type
     TTestClass<T> = class
     public
       function GetText(Param: T): string;
     end;

    procedure TForm1.Button1Click(Sender: TObject);
    begin
     with TTestClass<Integer>.Create do
       try
         Caption := GetText(1);
       finally
         Free;
       end;
     with TTestClass<Double>.Create do
       try
         Caption := GetText(1.1);
       finally
         Free;
       end;
    end;

    function TTestClass<T>.GetText(Param: T): string;
    var
     Info: PTypeInfo;
     Value: TValue;
    begin
     Result := '';
     Info := System.TypeInfo(T);
     Value := TValue.From<T>(Param);
     case Info.Kind of
       tkInteger: Result := IntToStr(Value.AsInteger);
       tkFloat: Result := FloatToStr(Value.AsExtended);
     end;
    end;



    Имхо, код GetText неудобочитаемый и вообще не сильно Object Pascal напоминает. А теперь представьте, что в реальном коде дженерики используются для сотни внутренних переменных, которые в методе надо туда-сюда конвертировать. Вот реально получается какая-то фигня. После месяца экспериментов думаю, может стоило все сделать вариантами

    Кто что думает по этому поводу и насколько часто этим у себя пользуетесь?
  • Rouse_ © (08.08.16 10:34) [1]
    Для такого простейшего случая дженерики избыточны. Нет смысла совать их во все подряд.
  • Игорь Шевченко © (08.08.16 10:47) [2]
    Всякий овощ приносит пользу, будучи употреблен надлежащим образом в надлежащее время, дженерики не исключение.

    По теме, да, пользуюсь, но в большинстве своем имеющимися в RTL классами.

    Вариант в данном примере тоже некрасив и не сопровожаем. Если переделывать проекты на новые возможности языка потому что это модно, лучше вместо этого заняться изобретением самодвижущегося пресс-папье, всяко больше пользы будет.
  • Pavia © (08.08.16 14:48) [3]
    Просто надо правильно пользоваться вы применили неправильный подход.

    Дженерики предназначены для обобщённое программирование. Вот вы должны были среди разных классов выделить единое для всех классов и это запихнуть в дженерик. А вы выдели разное.

    Хотя, конечно бывают и исключения. Так что небольшой case на 1-2 пукнта возможен.
  • maxsvt © (09.08.16 00:52) [4]
    Rouse_

    > Для такого простейшего случая дженерики избыточны

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

    > Вариант в данном примере тоже некрасив

    Так и я о том же. Даже простой пример с конвертированием в реальные типы получается некрасив. А в сложных методах - вообще жуть

    > Если переделывать проекты на новые возможности языка потому
    > что это модно

    Руководство хочет :)
    Pavia

    > Дженерики предназначены для обобщённое программирование

    Я понимаю. Понятна суть и, в общем, нравиться идея. Но впихнуть это в код старых проектов как-то не сильно пока удачно выходит
  • Германн © (09.08.16 02:04) [5]

    > Но впихнуть это в код старых проектов как-то не сильно пока
    > удачно выходит

    Ну вот почти все ответившие сказали что "впихнуть это" в код старых проектов по меньшей мере нецелесообразно. Так зачем тогда пытаться?
  • Dimka Maslov © (09.08.16 09:46) [6]
    В дельфи - не пользуюсь практически вообще из-за недоразвитой реализации. А вот в сях - весьма активно.
  • Игорь Шевченко © (09.08.16 10:48) [7]
    maxsvt ©   (09.08.16 00:52) [4]


    > Руководство хочет :)


    Тогда это не вопрос для форума, не так ли ? Ну или пригласить на форум руководство, чтобы узнать его точку зрения без испорченного телефона.
  • Pavia © (09.08.16 13:02) [8]

    > В дельфи - не пользуюсь практически вообще из-за недоразвитой
    > реализации. А вот в сях - весьма активно.

    А вот это хотелось бы обсудить. Реализация в си да и в Си# более богатая чем в Delphi. Но стоит ли переводить? Или есть технические ограничения которые припрятывают разрастанию различных коллекций?

    Вообще кто нибудь сравнивал дженирики на Си или Си# с теми что в Delphi?
  • Rouse_ © (09.08.16 13:49) [9]

    > maxsvt ©   (09.08.16 00:52) [4]

    Понятно. Я обычно дженерики для хранения структур использую с последующей сортировкой - очень удобно получается (ну как один из вариантов)
  • jack128 © (09.08.16 21:52) [10]

    > Вообще кто нибудь сравнивал дженирики на Си или Си# с теми
    > что в Delphi?

    А чего там сравнивать?
    Достоинства дженериков дельфи = пересечение достоинств дженериков C# и шаблонов С++
    Недостатки дженериков дельфи = объединение недостатков дженериков С# и шаблонов С++

    Раздувают бинарный код как шаблоны. Возможностей меньше чем в шарпе.
  • Pavia © (09.08.16 22:29) [11]

    > Достоинства дженериков дельфи = пересечение достоинств дженериков
    > C# и шаблонов С++
    > Недостатки дженериков дельфи = объединение недостатков дженериков
    > С# и шаблонов С++

    Самому руки не дойдут, посмотреть.

    В том то и дело что там отличия существенные. Нет множественного наследования. Поэтому в ряде коллекций внутри дженерика приходится добавлять ещё дженерик.  

    TList<T> = class(TEnumerable<T>)
    ...
       type  {Тип в типе}
         TEnumerator = class(TEnumerator<T>)
         private
           FList: TList<T>;
           FIndex: Integer;
           function GetCurrent: T;
         protected
           function DoGetCurrent: T; override;
           function DoMoveNext: Boolean; override;
         public
           constructor Create(const AList: TList<T>);
           property Current: T read GetCurrent;
           function MoveNext: Boolean;
         end;
       
       function GetEnumerator: TEnumerator; reintroduce;
     end;


    Притом таких типов как TEnumerator - с одним названием в юните объявлена целая куча.
    Отсюда ущербность.
  • Игорь Шевченко © (09.08.16 22:54) [12]

    > Отсюда ущербность.


    Чья ? Развелось ламеров, плюнуть некуда, всяко в ламера попадешь.
  • Dimka Maslov © (10.08.16 09:44) [13]

    > Вообще кто нибудь сравнивал дженирики на Си или Си# с теми
    > что в Delphi?


    Чтобы не переходить в крайности, то это как сталь и алюминий.
    Взять хотя бы вот это:
    В С++ шаблоном может функция. В Дельфи - только метод, если хочешь функцию городи класс. Вопрос: А [зачем]?
    В С++ я спокойно могу написать такое
    template <class T> CTemplate
    {
    public:
      T& Get() { T* R = new T; R->AddRef(); return R; }

    }


    Почему я не могу написать в Дельфи

    TGeneric<T> = class
    public
     function Get: T;
    end;

    function TGeneric<T>.Get: T;
    var
     R: T;
    begin
     R = T.Create;
     R.AddRef();
     Result := R;
    end;



    Другими словами шаблон в C++ это не более чем продвинутая директива препроцессора, а что такое дженерик в Delphi?
  • DayGaykin © (10.08.16 22:54) [14]
    Было бы прикольно если бы можно было примерно так:


    function TTestClass<T>.GetText(Param: T): string;
    begin
     Result := SomeToStr(Param);
    end;


    где:

    function SomeToStr(A: String): String; overload;
    function SomeToStr(A: Integer): String; overload;
    function SomeToStr(A: Double): String; overload;

  • Jack128 © (10.08.16 23:18) [15]
    C++ ждёт тебя
  • maxsvt © (11.08.16 00:38) [16]
    Германн

    > Так зачем тогда пытаться

    Была мысль, что что-то это упростит. Когда появилась сама идея
  • maxsvt © (11.08.16 00:40) [17]
    DayGaykin - ну так обьявите
    function SomeToStr(A: String): String; overload;
    function SomeToStr(A: Integer): String; overload;
    function SomeToStr(A: Double): String; overload


    внутри класса
  • Германн © (11.08.16 01:43) [18]

    >  maxsvt ©   (11.08.16 00:38) [16]
    >
    > Германн
    >
    > > Так зачем тогда пытаться
    >
    > Была мысль, что что-то это упростит. Когда появилась сама
    > идея
    >

    Создание новых проектов это действительно может упростить. Но не обязательно. А вот перевод старых проектов на дженерики вряд ли что-то упростит.
  • Игорь Шевченко © (11.08.16 11:01) [19]

    > А вот перевод старых проектов на дженерики вряд ли что-то
    > упростит.


    Аргументы последуют ?
  • Rouse_ © (11.08.16 14:23) [20]
    Серега, конечно, слегка перегнул, но приведу аргументы для ИШ :)
    Работает - не трожь :)
  • Германн © (12.08.16 00:42) [21]

    > Rouse_ ©   (11.08.16 14:23) [20]

    Безусловно - это главный аргумент. :)
  • Германн © (12.08.16 01:47) [22]
    Ждёмс аргументы от противной стороны. :)
  • maxsvt © (12.08.16 18:51) [23]
    Игорь Шевченко
    [q]Аргументы последуют[/q]
    Собственно во многих классах были общие вещи, которые в первом приближении можно было упростить дженериками. Но практика показала обратное
  • Eraser © (13.08.16 03:17) [24]

    > Руководство хочет :)

    замени все списки в проекте на списки (стандартные) с поддержкой дженериков. и польза будет и начальство порадуется и работы не много )
  • Д7 (14.08.16 14:15) [25]
    А можно подробнее что там практика показала и об чём это конкретно?

    Мне больше интересно - как это устроено на низком уровне? И на Си и на Делфи.
    Компилятор типа смотрит какие типы были использованы в коде и делает "развёртку" шаблона на много обычных классов? И подставляет в код конкретные сгенерированные типы?

    З.Ы. Как вы делаете код на белом фоне и с нумерацией строк? Что за тег?
  • Игорь Шевченко © (14.08.16 15:12) [26]
    Удалено модератором
  • Игорь Шевченко © (14.08.16 15:13) [27]

    > Что за тег?


    DELPHI в угловых скобках. Надо на главной странице написать
  • stas © (06.09.16 14:37) [28]
    Удалено модератором
  • stas © (06.09.16 14:46) [29]

    > Pavia ©   (09.08.16 13:02) [8]
    > Вообще кто нибудь сравнивал дженирики на Си или Си# с теми
    > что в Delphi?


    В C# есть linq, с помощью которого работать с Generic коллекциями намного проще.
Есть новые Нет новых   [134431   +15][b:0][p:0.002]