DataObject.SetAudio should be exposed with a new overload taking Span<byte>
See original GitHub issueThe DataObject
class currently exposes two audio overloads. The first one taking a byte[]
calls the second who takes a Stream
.
Rationale
Since the introduction of Span<T>
it become preferable exposing APIs using Span<T>
because they are stack-only types minimizing the use of the garbage collector and easily allows slicing the referenced memory.
Proposed API
namespace System.Windows.Forms
{
public partial class DataObject : IDataObject
{
// Existing methods
public virtual void SetAudio(byte[] audioBytes);
public virtual void SetAudio(Stream audioStream);
// Proposed method
public virtual void SetAudio(Span<byte> audioBytes);
}
}
An additional advantage of Span<T>
is that it self describes the contiguous memory to be processed from the API. The existing overload taking byte[]
does not even allow to specify an offset and length of the array.
Since the current overloads allow specifying an empty interval and only check whether the parameter (byte[]
or Stream
is null), it is also possible to avoid any parameter check since Span<T>
is a ref struct
and cannot be null.
The parameter Span<byte>
can be empty, as it is for the other overloads.
Implementation
The proposed implementation of the new public API is the following:
public virtual void SetAudio(Span<byte> audioBytes)
{
var stream = new MemoryStream(audioBytes.Length);
stream.Write(audioBytes);
stream.Seek(0, SeekOrigin.Begin);
SetAudio(stream);
}
The MemoryStream is not disposed as it is not directly consumed from the called methods. The other overload does the same.
The PR for this new API is available and contains also a test with four different types of blobs, including an empty one.
Issue Analytics
- State:
- Created 5 years ago
- Comments:14 (14 by maintainers)
Video
We aren’t experts on
IDataObject
but what is the benefit of usingSpan<T>
here? TheStream
API allows you to slice the data already, and it seems the implementation pushes the state into the heap.For this scenario
Span<T>
doesn’t make sense; at the very minimum it would need to beMemory<T>
(becauseSpan<T>
cannot be stored on the heap). However, this seems to complicate the API surface more than it helps.If slicing the array would be common, I suggest we instead add an overload that simply accepts two ints, or an
ArraySegment<T>
.Thanks @raffaeler - this is helpful for context! cc @zsd4yr @JeremyKuhne