Span<T> là cửa sổ nhìn vào một vùng bộ nhớ liên tục — mảng, chuỗi, buffer stack hay bộ nhớ unmanaged — cho phép cắt lát mà không cấp phát và không copy.
ReadOnlySpan<char> line = "2026-08-06|ORD-77|150000";
var date = line[..10]; // no substring allocation
var rest = line[11..];So với Substring/ToArray, cách này bỏ hẳn các bản copy trung gian, rất đáng dùng ở đường parse nóng.
Vì sao không dùng được trong async: Span<T> là ref struct, buộc phải nằm trên stack. Compiler cần bảo đảm nó không bao giờ trở thành field trên heap. Mà một method async được biên dịch thành state machine, và mọi biến cục bộ sống qua một await phải được lưu thành field của state machine đó — có thể nằm trên heap. Vì vậy Span<T> không được sống qua await (cũng như không được dùng trong iterator hay bị lambda capture).
Memory<T> là phiên bản lưu được trên heap cho đúng nhu cầu đó: giữ nó qua await, rồi khi cần đọc/ghi thì lấy span ra ở đoạn code đồng bộ.
async Task ReadAsync(Memory<byte> buffer, Stream s)
{
int read = await s.ReadAsync(buffer); // Memory crosses the await
Process(buffer.Span[..read]); // Span only in sync code
}Ghép với ArrayPool<T> và stackalloc sẽ cho đường xử lý gần như không cấp phát.