There are two similar but different types in .net: ReadOnlySpan<T> и ReadOnlySequence<T>. Former is an abstraction over continous array of elements of T that you can’t change. Latter is chain from those arrays. Former is useful when you’re writing code that accepts arrays: usual arrays, stack-allocated arrays (hello, stackalloc), arrays in unmanaged memory and so on. It has some overhead, which was discussed earlier.
ReadOnlySequence<T>, on my opinion, is most useful when you have some network IO, because when you expect million (or even thousand) of 64bit integers from network, you can’t assume that you’ll get that numbers in one batch. I mean, you can assume, but it won’t be that way everytime. In most cases, you’ll get chain of buffers.
I try to write library which will be useful in both cases. And we stumble upon particular weakness of C#: we need to write same method twice. Look to excerpt, full code is here.
We have problems:
- Both types are structs. They don’t implement any interfaces, so, we can’t write any common code for some
- We can’t make this code generic, because
ReadOnlySpan<T>is special stack-only struct, which can’t be type parameter of generic method.
- We can’t create
ReadOnlySpan<T>without copy, because
ReadOnlySequence<T>is not made from spans, it is made from
ReadOnlyMemory<T>which is similar to Span, but not stack-only, and creating memory from span involves copying.
- We can’t change signature
ReadOnlyMemory<T>, because they’re different.
ReadOnlyMemory<T>can’t be used to work with unmanaged memory or stack-allocated array. So,
ReadOnlySpan<T>can represent a lot more arrays.
- You can’t represent sequence by span for obvious reasons.
I don’t see any solution to that problem, except duplicating code. I remember when we have good old C++, when you can do this (thanks, Yauheni Akhotnikau for corrected code):comments powered by Disqus