-
Why ArraySegment implements interfaces explicitly? According to the documentation of using System;
using System.Linq;
using System.Collections.Generic;
using System.Collections;
public readonly struct Color4
{
public readonly byte R;
public readonly byte G;
public readonly byte B;
public readonly byte A;
public Color4(byte r, byte g, byte b, byte a)
{
R = r;
G = g;
B = b;
A = a;
}
}
public readonly struct MyArraySegment<T> : IReadOnlyList<T>
{
private readonly int count;
private readonly int offset;
private readonly T[] array;
public MyArraySegment(T[] array)
{
this.array = array;
offset = 0;
count = array.Length;
}
public MyArraySegment(T[] array, int offset, int count)
{
this.array = array;
this.offset = offset;
this.count = count;
}
public T this[int index] {
get => array[offset + index];
set => array[offset + index] = value;
}
public int Count => count;
public IEnumerator<T> GetEnumerator()
{
throw new NotImplementedException();
}
IEnumerator IEnumerable.GetEnumerator()
{
throw new NotImplementedException();
}
}
public class Bitmap
{
private Color4[] pixels;
public static Bitmap CreateBoxed(IReadOnlyList<Color4> pixels)
{
var bitmap = new Bitmap();
bitmap.pixels = pixels.ToArray();
return bitmap;
}
public static Bitmap Create<TPixelArray>(TPixelArray pixels)
where TPixelArray : IReadOnlyList<Color4>
{
var bitmap = new Bitmap();
bitmap.pixels = new Color4[pixels.Count];
for (int i = 0; i < pixels.Count; i++) {
bitmap.pixels[i] = pixels[i];
}
return bitmap;
}
public static void Test()
{
var array = new Color4[4];
var list = new List<Color4>();
var segment = new ArraySegment<Color4>(array);
var mySegment = new MyArraySegment<Color4>(array);
var bmpArray = Bitmap.Create(array);
var bmpList = Bitmap.Create(list);
var bmpSegment = Bitmap.Create(segment);
var bmpMySegment = Bitmap.Create(mySegment);
var bmpBoxedSegment = Bitmap.CreateBoxed(segment);
}
} |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment 1 reply
-
I think you're misinterpreting that documentation. It says that value types are boxed when the type does not implement/override a method from a base class. For example, calling To verify this, I've run your test code using Benchmark.Net: [ShortRunJob]
[MemoryDiagnoser]
public class Benchmark
{
Color4[] array = new Color4[4];
List<Color4> list = new(new Color4[4]);
ArraySegment<Color4> segment = new(new Color4[4]);
MyArraySegment<Color4> mySegment = new(new Color4[4]);
[Benchmark]
public Bitmap Array() => Bitmap.Create(array);
[Benchmark]
public Bitmap List() => Bitmap.Create(list);
[Benchmark]
public Bitmap Segment() => Bitmap.Create(segment);
[Benchmark]
public Bitmap MySegment() => Bitmap.Create(mySegment);
[Benchmark]
public Bitmap BoxedSegment() => Bitmap.CreateBoxed(segment);
} The results are (ignore the timing and only look at the Allocated column):
As you can see, implementing the interface explicitly does not cause additional allocations. |
Beta Was this translation helpful? Give feedback.
I think you're misinterpreting that documentation. It says that value types are boxed when the type does not implement/override a method from a base class. For example, calling
ToString()
on yourMyArraySegment<T>
would cause this kind of boxing. ButArraySegment<T>
does implementIReadOnlyList<T>
, so no boxing occurs; it doesn't matter that it's implemented explicitly. (In fact, the documentation calls out this boxing cannot happen with interfaces: "This last case can occur only whenmethod
was defined onObject
,ValueType
, orEnum
and not overridden bythisType
.")To verify this, I've run your test code using Benchmark.Net: