How it works
A span describes a contiguous region of memory without being a new array containing copied elements. AsSpan selects two elements starting at index one. ReadOnlySpan prevents this view from writing through its indexer, but the underlying array still has another writable owner: the values variable.
Changing values[1] to twenty-five is visible through middle because both access the same storage. The view's length remains two. This is an important distinction between a read-only view and an immutable snapshot. A view restricts operations through one reference; it does not automatically prevent every other reference from modifying the memory.
The array range expression values[1..3] has a different result type and behavior. It produces a new array containing the selected elements. The end index is exclusive, so the copied values are twenty-five and thirty. A later change to values[2] does not change copied[1], which still prints thirty.
Spans have lifetime restrictions because they can refer to memory that must not outlive its valid scope. Keep this example in synchronous code. Do not assume a span can be stored in an ordinary object field or retained across arbitrary asynchronous suspension. Those compiler restrictions protect the lifetime of the memory being viewed.
Practice by writing a synchronous Sum(ReadOnlySpan<int>) method and passing both the full array and its middle region. Add checks for an empty span and a single element. Then compare passing a span with creating an array slice when the operation only needs to read a few values once.
Choose the API according to ownership and lifetime requirements. Copying may be exactly right when a caller needs an independent snapshot; a span may be appropriate for a short, local calculation over existing storage. Avoid claiming an optimization without measuring a meaningful workload, and always preserve the visible behavior expected by callers.
A working example
using System;
using System.Linq;
using System.Collections.Generic;
using System.Globalization;
using System.Text;
using System.Text.Json;
using System.Text.Json.Serialization;
using System.Threading;
using System.Threading.Tasks;
using System.Runtime.CompilerServices;
int[] values = { 10, 20, 30, 40 };
ReadOnlySpan<int> middle = values.AsSpan(1, 2);
values[1] = 25;
Console.WriteLine(middle[0]);
Console.WriteLine(middle.Length);
int[] copied = values[1..3];
values[2] = 99;
Console.WriteLine(copied[1]);
Expected output
25 2 30
A span views existing storage; an array range expression creates a new array.