Это не мешает особо, если компилировать в уме.
В современном C# есть кортежи с именованными полями. Посмотрите, как у них сделано. Очень хорошая штука - просто руки не доходят.
(int x, string s) t;
t = (x: 0, s: "abc");
В паскале это выглядело бы как то так:
var t: (x: integer; s: string);
t := (x := 0, s := 'abc');
Однако создание экземпляра через список имён и значений уже есть с анонимными классами. Поэтому если дополнять их вместо создания новой фичи - должно быть на много проще реализовать. Если через них - как то так:
var t: class(x: integer; s: string);
t := new class(x := 0, s := 'abc');
Относительно предыдущего кода - в первой строчке добавилось только class
, а во второй new class
перед скобками.
При этом функционал второй строчки уже полностью реализован.
Вот только уживутся ли они с лямбдами, LINQ и автоприведением типа?
Полагаю, что возможно следующее использование этих фич:
- Кортежи - для примитивной группировки значений, скорее, для внутренних нужд.
- Анонимные классы (как показано выше) - для использования в интерфейсах модулей, библиотек, классов и записей, поскольку они позволят задавать имена свойств, несущих смысловую нагрузку.
Вы не передадите анонимные классы между dll.
А это и не надо. Анонимные классы, если добавить возможность описывать их тип - получат примерно ту же область применения что лямбды (то есть анонимные подпрограммы). А анонимность лямбд как раз заключается в том, что их видно и можно использовать только там, где они описаны. И нигде больше их существование не показывается.
Это позволяет реализовывать всякие мелкие кишки. Как в случае лямбд - делегаты, как те что передаются в методы Linq
. Если заменить лямбду глобальной подпрограммой - добавится лишнее и неудобное имя.
Если надо класс который будет видно всюду - надо делать НЕ_анонимный, то есть обычный класс.
Ну а для класса с авто генерацией конструктора и прочих, муторных в реализации, удобств - есть автоклассы.
Ну то есть как это не надо?
Вот, пример приводили в этом топике.
Это не будет работать в dll при попытке определения через анонимный класс
-
Почему не будет? Читать и записывать значения каждого элемента можно будет.
-
Да совместимый тип нельзя будет сделать. Но я говорил что логически не правильно использовать анонимность публично. То есть можно и лямбду присвоить публичной переменной/полю, видимой вне библиотеки, но обычно это не более чем выстрел себе в ногу.
Но - это правило общего случая, у него могут быть редкие исключения. К примеру лямбда может быть дефолтным значением какого то поля с типом делегата, которое можно изменять извне библиотеки. -
Вообще то можно между паскалевской библиотекой и паскалевской программой - сделать совместимость. Анонимные классы разворачиваются в типы с недопустимыми знаками в названии, поэтому их легко найти при чтении библиотеки.
-
Пример который привёл @MrFresnel - это явно что то из паскалевского модуля который он сделал как прокладку между своей библиотекой и паскалем. Это понятно потому что оно написано на паскале. А значит тут это проблемы не будет.
Проблемы не будет если сделать это на базе кортежей.
Надо только выяснить, как обеспечивается совместимость кортежей с именованными полями в C# и есть ли она вообще.
Нет. Вы ошиблись. Это был просто абстрактный пример. В модуле моём такого нет. Это есть в библиотеке, но пока без применения именованных кортежей (пока в той части библиотеки рефакторинг не проводил). Реализация на анонимных классах - она проста. Но с точки зрения совместимости библиотеки и PascalABC.NET лучше реализация на кортежах. Однако, моя библиотека, поскольку она не стандартная и вряд ли ей когда нибудь станет (потому что в случае включения её как стандартную придётся тянуть ещё и модуль, точнее с этой точки зрения она не легковесная, а также потому что имеется пересекающийся функционал), не может быть сильным аргументом для того, чтобы разработчики только из-за неё делали подобную функциональность на кортежах.
type
T = class
end;
function operator implicit(self: T): integer; extensionmethod := 0; // error here
begin
end.
При компиляции выдаёт:
Program1.pas(5) : extension-операторы преобразования типов допустимы только для классов из других сборок .NET
Данное ограничение запрещает определять extension операторы преобразования для массивов.
PABCSystem
строчка 9413:
/// Возвращает индекс последнего минимального элемента
function LastIndexMin<T>(Self: array of T): integer; extensionmethod; where T: System.IComparable<T>;
begin
Result := Self.LastIndexMin(Self.Count - 1);
end;
.Count
плохо применять к массивам. .Count
воспринимает массив как yield
последовательность и проходит по всем элементам перед тем как дать результат, в то время как .Length
только читает внутреннее поле.
Исправили. Спасибо.
Как насчёт того, чтобы в стандартную библиотеку добавить метод расширения IsPrime для целых, который будет возвращать true, если число простое?
function IsPrime(self: integer): boolean; extensionmethod;
begin
if self <= 1 then exit;
var i := 2;
while i * i <= self do
begin
if self mod i = 0 then exit;
i += 1;
end;
Result := true;
end;
Добавлять нужно 2. Все простые числа кроме 2 нечётные. Работать будет медленно. Лучше использовать небольшую таблицу с уже вычисленными простыми числами. Более того все следующие делители должны быть простыми.
Это можно, но я не уверен стоит ли. Ну, сейчас сделаю.