Home > Software engineering >  Weird span behaviour
Weird span behaviour

Time:11-30

I have gotten some weird result when playing around with Spans in C# and I'm not sure what I'm doing wrong. In order to boil the problem down I made a simple test case:

        public static void DecSpans(Span<byte> b1, Span<byte> b2)
        {
            for (int i = 0; i < b1.Length;   i)
            {
                b1[i] = (byte)(b1[i] - b2[i]);
            }

        }

        [DataTestMethod]
        public void TestSpan()
        {
            byte[] buf1 = new byte[4] { 1, 2, 3, 4 };
            DecSpans(buf1[..], buf1);
            Assert.IsTrue(buf1.All(b => b == 0));
        }

buf1 is not modified for some reason when I make it a slice. If I remove the [..] then buf1 is modified. Am I doing something illegal here?

CodePudding user response:

Nothing to do with spans.

When you use the slice operator on a type, you get back an instance of the same type. So when you use a slice on an array, you get back a new array.

Therefore buf1[..] is the same as buf1.ToArray(): it allocates a new array and copies buf1 into it. You then re-assign elements in this temporary array, and discard it.

To create a span which points to an array, use buf1.AsSpan().


I think you're used to Rust, where a slice produces its own dedicated type. That's not how C# works. For instance, it's not safe to create a Span<T> which points to the underlying storage of a List<T> (as that storage can be reallocated as the list grows). If a slice always produces a Span<T>, then slicing a list would either by forbidden, or unsafe, neither of which is desirable (and C# has no borrow checker to make this safe). Following the rule that a slice returns an instance of the same type alleviates this.

  •  Tags:  
  • c#
  • Related