type
TClass<T> = static class // Program3.pas(2) : Статические классы не могут быть генериками
end;
begin
end.
В C# аналогичный код компилируется:
using System;
namespace ConsoleApp1
{
static class C<T>
{
}
static class Program
{
static void Main(string[] args)
{
}
}
}
. Если Вы проверяли реакцию компиляторов других языков, то было не лишним выложить результаты тестов.
Снятие ограничение может быть полезно при желании избежать дублирование кода. К примеру, без ограничения код класса мог бы выглядеть так:
static class SomeClass<T>
{
public static void A() // Как-то используем T.
{
}
public static void B() // Как-то используем T.
{
}
}
, с:
static class SomeClass
{
public static void A<T>() // Как-то используем T.
{
}
public static void B<T>() // Как-то используем T.
{
}
}
, Тем, более, если на T должны накладываться какие-либо ограничения, которые едины для методов данного класса, то было бы удобней перечислять их в where класса, а не каждого метода.
Потому что тип шаблонного класса определяется при создании экземпляра класса. Экземпляр статического класса создать нельзя, как и наследовать от класса.
Если это особенность именно PascalABC.Net, то это весомый аргумент. Но, напомню, что в C# мы наблюдаем противоположное поведение - статические классы могут быть шаблонными.
<личное мнение>И так достаточно оттуда позаимствовали. Лично для меня теперь всего хватает.</личное мнение>
Если разработчики подтвердят, что это действительно особенность данного компилятора, то вопрос можно будет считать закрытым.
<личное мнение>Думаю, что эту тему можно оставить открытой для сравнения языков в контексте этого вопроса. Сравнительный анализ - полезная вещь, особенно если новички зададутся вопросом отличия PascalABC.Net от других языков.</личное мнение>
type
t1<T> = {static{} class
class procedure p1 := writeln(typeof(T));
end;
begin
t1&<byte>.p1;
t1&<word>.p1;
end.
Для шаблонных типов создаётся тип в котором T заменят на что то - когда в коде как то где то есть указание каким должен быть T. Для этого не обязательно создавать экземпляр.
Ну, может под горячую руку и зря запретил. Только что такое статические генерик-классы и кому они нужны, вот в чем вопрос. Если кто найдет в стандартной библиотеке пример, я разрешу.
В стандартной библиотеке не знаю, я далеко не всюду копался, но вот, к примеру:
type
UsedCounter<T> = {static{} class
private class m_used: integer;
public class procedure Inc :=
m_used += 1;
public class property Used: integer read m_used;
end;
function f1<T>(o:T):object;
begin
//ToDo что то делаем с "o"
UsedCounter&<T>.Inc;
end;
begin
loop 3 do f1(byte(0));
loop 5 do f1('');
writeln(UsedCounter&<byte>.Used); // 3
writeln(UsedCounter&<integer>.Used); // 0
writeln(UsedCounter&<string>.Used); // 5
end.
Работает в основном как словарь, но более красиво и, вроде, быстро (надо провести ещё некоторые тесты).
Самое приятное - компилятор тут выполнит всю необходимую работу. (всм не надо создавать словарь, не надо писать typeof каждый раз, чтоб получить значение для определённого типа)
Даже static-abstract/-sealed классы запрещены, чего уж усложнять? Тем более наследование для статических классов запрещено. И зачем наследоваться от самого себя? Какая польза?