I've been looking for a way to extract slices from a 2D matrix without having to actually reallocate-copy the contents, and
public static Span<float> Slice([NotNull] this float[,] m, int row)
{
if (row < 0 || row > m.GetLength(0) - 1) throw new ArgumentOutOfRangeException(nameof(row), "The row index isn't valid");
return Span<float>.DangerousCreate(m, ref m[row, 0], m.GetLength(1));
}
I've checked this method with this simple Unit tests and apparently it works:
[TestMethod]
public void Foo()
{
float[,] m =
{
{ 1, 2, 3, 4 },
{ 5, 6, 7, 8 },
{ 9, 9.5f, 10, 11 },
{ 12, 13, 14.3f, 15 }
};
Span<float> s = m.Slice(2);
var copy = s.ToArray();
var check = new[] { 9, 9.5f, 10, 11 };
Assert.IsTrue(copy.Select((n, i) => Math.Abs(n - check[i]) < 1e-6f).All(b => b));
}
This doesn't seem right to me though. I mean, I'd like to understand what's exactly happening behind the scenes here, as that ref m[x, y]
part doesn't convince me.
How is the runtime getting the actual reference to the value at that location inside the matrix, since the this[int x, int y]
method in the 2D array is just returning a value and not a reference?
Shouldn't the ref
modifier only get a reference to the local copy of that float
value returned to the method, and not a reference to the actual value stored within the matrix? I mean, otherwise having methods/parameters with ref
returns would be pointless, and that's not the case.
I took a peek into the IL for the test method and noticed this:
Now, I'm not 100% sure since I'm not so great at reading IL, but isn't the ref m[x, y]
call being translated to a call to that other Address
method, which I suppose just returns a ref
value on its own?
If that's the case, is there a way to directly use that method from C# code?
And is there a way to discover methods like this one, when available?
I mean, I just noticed that by looking at the IL and I had no idea it existed or why was the code working before, at this point I wonder how much great stuff is there in the default libs without a hint it's there for the average dev.
Thanks!
Slice
so I do not understand how you are testing it. – Sarmentumthis[int x, int y]
returns a value? You can dom[2, 1] = 7;
, correct? – Crossletthis[int, int]
method on a 2DArray
, that returns anint
value, I'm not sure I understand your question. My point here is that the getter in question is only supposed to return a value, and I wasn't excepting the compiler to replace that call with an entirely different method (apparently), and I'd like to know the implementation details or what's exactly happening. – Province