Span<T> и потоки в.NET Framework
Я работаю с сетевыми буферами и потоками, и Span и Memory будут идеально соответствовать требованиям приложения.
Что касается этого вопроса, я бы хотел, чтобы поток принимал Span в качестве параметра. Я знаю, что это реализовано в.NET Core 2.1, но мне было интересно, есть ли способ получить эту функциональность также в.NET Framework? (Я использую 4.7.1)
Что-то вроде:
Span<Byte> buffer = new Span<byte>();
stream.Read(buffer);
2 ответа
Мне удалось решить эту проблему, написав метод расширения для класса Stream и реализовав стандартное поведение.NET Core для работы с Span.
public static int Read(this Stream thisStream, Span<byte> buffer)
{
byte[] sharedBuffer = ArrayPool<byte>.Shared.Rent(buffer.Length);
try
{
int numRead = thisStream.Read(sharedBuffer, 0, buffer.Length);
if ((uint)numRead > (uint)buffer.Length)
{
throw new IOException(SR.IO_StreamTooLong);
}
new Span<byte>(sharedBuffer, 0, numRead).CopyTo(buffer);
return numRead;
}
finally { ArrayPool<byte>.Shared.Return(sharedBuffer); }
}
а также
public static void Write(this Stream thisStream, ReadOnlySpan<byte> buffer)
{
byte[] sharedBuffer = ArrayPool<byte>.Shared.Rent(buffer.Length);
try
{
buffer.CopyTo(sharedBuffer);
thisStream.Write(sharedBuffer, 0, buffer.Length);
}
finally { ArrayPool<byte>.Shared.Return(sharedBuffer); }
}
К сожалению, поскольку эта функциональность еще не реализована в.Net Standard, она не включена в.Net Framework.
Редактировать: я помню, что я где-то читал, что есть предварительный пакет NuGet, который можно использовать с.Net Framework
Проверьте NuGet с System.Memory
Принятое решение отлично работает!
Однако в некоторых ситуациях, когда я использую общий проект, нацеленный на.NET Core и.NET Framework вместе, я использую как массив, так и Span<T>
:
var _buffer = new byte[1024*1024];
Span<Byte> buffer = _buffer;
#if NETCOREAPP3_1
stream.Read(buffer);
#else
stream.Read(_buffer);
#endif
Таким образом, я могу избежать небольших накладных расходов на аренду / копирование / возврат массива из ArrayPool.