Из прочтения комментариев в Memory<T>
похоже, что его можно разорвать.
Однако, похоже, есть два места, где это действительно имеет значение: Memory<T>.Pin()
и Memory<T>.Span
.
Важно отметить, что (насколько я могу понять) мы не заботимся о разрыве таким образом, что означает, что мы все еще указываем на где-то в объекте, к которому мы обращаемсяк - хотя наш абонент может получить некоторые странные данные, которых он не ожидал, это безопасно в том смысле, что они не получат AccessViolationException.У них просто будет состояние состязания, которое приводит к неожиданным результатам, вследствие наличия несинхронизированного многопоточного доступа к полю.
Memory<T>.Span
получает Span<T>
от Memory<T>
.У него есть этот комментарий :
Если экземпляр Memory или ReadOnlyMemory порван, это средство получения свойства имеет неопределенное поведение.Мы пытаемся обнаружить это условие и генерируем исключение, но возможно, что порванная структура может показаться нам действительной, и мы вернем нежелательный диапазон.Такой промежуток всегда гарантированно находится в границах по сравнению с исходным экземпляром Memory, поэтому использование промежутка не приведет к AV-процессу.
Таким образом, мы можем абсолютно разорваться Memory<T>
, а затем попробуйте создать Span<T>
из него.В этом случае в коде есть проверка, которая выдает исключение, если Memory<T>
разрывается таким образом, что теперь он ссылается на некоторую память вне объекта, на который ссылается Memory<T>
.
Если он порвался так, как он все еще ссылается где-то в исходном объекте, то это нормально - наш вызывающий может не читать то, что ожидал прочитать, но, по крайней мере, он не получит исключение AccessViolationException, что и являетсямы пытаемся избежать.
Обратите внимание, что Span<T>
не может выполнить эту же проверку (даже если бы захотел).Memory<T>
хранит ссылки на объект, начальное смещение и длину.Span<T>
сохраняет только ссылки на некоторый адрес памяти внутри объекта и его длину.
Memory<T>.Pin()
- это метод unsafe
, который имеет этот комментарий :
Возможно, что приведенная ниже логика может привести к AV, если структура порвана.Это нормально, так как вызывающий объект ожидает использовать необработанные указатели, мы не обязаны сохранять его таким же безопасным, как и другие API на основе Span.
Опять же, мы можем порвать таким образом, что мыбольше не ссылаются где-то внутри объекта, на который мы ссылаемся.Однако этот метод unsafe
, и нам все равно.