Новые функции, связанные с Span
в. NET делают использование ввода-вывода с отображением в памяти намного более точным, и это также может быть очень безопасным, хотя MS еще не делает его надежным, и я не уверен если я вижу все подводные камни.
Первый облом в том, что MemoryMappedFile
все еще дает мне только указатель на отображенную память, а не промежуток:
var mmf = MemoryMappedFile.CreateFromFile(name + ".mmf", FileMode.Create, name, length);
var mmv = mmf.CreateViewAccessor();
mmv.SafeMemoryMappedViewHandle.AcquirePointer(ref ptr);
Это само по себе требует использования о небезопасном ключевом слове и опции компилятора, заставляя меня думать.
Но по крайней мере я могу создать Span
из этого как new Span<Byte>(ptr, length)
, и оттуда использовать его безопасно.
Там Тем не менее, по-прежнему необходимо приводить к пользовательским, неуправляемым типам структур, чтобы эффективно использовать память, отображаемую в IO. Поэтому я рассматриваю этот метод расширения для переинтерпретации приведений:
public static class SpanExtensions
{
public static unsafe Span<T> Cast<T>(this Span<Byte> bytes)
where T : unmanaged
{
fixed (byte* ptr = &bytes.GetPinnableReference())
return new Span<T>(ptr, bytes.Length / sizeof(T));
}
}
Все эти небезопасные ключевые слова заставляют меня немного нервничать, и я хотел бы, чтобы кто-то в курсе подтвердил некоторые мои предположения:
- Нет части поверхности IO API с отображением в памяти, которую я мог бы использовать без ключевого слова unsafe и переключателя компилятора, если я хочу получить
Span<T>
для некоторого неуправляемого типа T
. - Указатель, полученный от
AcquirePointer
, уже закреплен (документация ничего об этом не говорит, но я предполагаю, что отображенная память находится вне ответственности G C). - Мое приведенное выше расширение для литья безопасно, даже в случае, когда я использую его в течение
Span
с управляемой памятью (например, Byte[]
), поскольку я ограничиваю возможность преобразования неструктурированными структурами, которые не могут содержать ссылок.
Правильно?