Здравствуйте, Serginio1, Вы писали:
S>генерик матх это упрощение работы с числовыми типами. Расширение описания интерфейсов с перегрузкой операторов.
Помимо генерик матх, static virtual members позволяют, например, обойти ограничение ограничений на конструкторы (pun intended).
Допустим, я хочу, чтобы меня параметризовывали типом, у которого есть конструктор от 1го строкового параметра. В современном дотнете я так сделать не могу, придётся реализовывать двухфазную инициализацию, или городить городушки с активатором (ненадёжно), либо дополнительно параметризовывать фабрикой:
| двухфазная инициализация |
| public interface IRequest: IDisposable
{
void Init(string url);
void Send(byte[] data);
}
public static Send<T>(string url, byte[] data)
where T: IRequest, new
{
using(var t = new T()) // :(
{
t.Init(url);
t.Send(data);
}
}
|
| |
| фабрика |
| public interface IRequest: IDisposable
{
void Send(byte[] data);
}
public interface IRequestFactory<T>
where T: IRequest
{
T Create(string url);
}
public static Send<T, F>(string url, byte[] data)
where T: IRequest, new
where F: IRequestFactory<T>, new
{
var f = new IRequestFactory(); // :( Ну, мы, конечно можем это закешировать, или обойти через struct, но осадочек остаётся.
using(var t = f.Create(url))
t.Send(data);
}
|
| |
При наличии static virtual всё это можно свернуть в значительно более простую, понятную, и компактную запись:
public interface IRequest<T>: IDisposable
where T: IRequest<T>
{
static virtual T Create(string url);
void Send(byte[] data);
}
public static Send<T>(string url, byte[] data)
where T: IRequest
{
using(var t = T.Create(url))
t.Send(data);
}