-
Notifications
You must be signed in to change notification settings - Fork 4.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add Array.Fill method for multi-dimensional array #47213
Comments
I couldn't figure out the best area label to add to this issue. If you have write-permissions please help me learn by adding exactly one area label. |
I think that the area is area-System.Runtime. |
How about allowing MD array to convert to spans? |
If that helps prioritize this addition, I've just hit a use case for this in my real-life project. |
Also encountered this in a real-world project! Suggested implementation isn't ideal though, this should be superior, supporting arbitrary rank, managed types and faster performance: public static void Fill<T>(Array array, T value) {
ArgumentNullException.ThrowIfNull(array);
var elementType = array.GetType().GetElementType();
if (elementType is null)
{
throw new ArgumentException("Array without element type", nameof(array));
}
if (elementType.IsValueType && value == null)
{
throw new ArgumentNullException(nameof(value));
}
if (elementType.IsAssignableFrom(value?.GetType()) is not true && value != null)
{
throw new ArgumentException("Must be assignable to array's element type", nameof(value));
}
if (array.Length == 0) { return; }
if (!elementType.IsValueType || elementType != value?.GetType())
{
var indices = new int[array.Rank];
while (true)
{
array.SetValue(value, indices);
for (var i = 0; i < array.Rank; i++)
{
indices[i]++;
if (indices[i] < array.GetLength(i)) { break; }
if (i == array.Rank - 1) { return; }
indices[i] = 0;
}
}
}
else
{
unsafe
{
fixed (void* ptr = &MemoryMarshal.GetArrayDataReference(array))
{
new Span<T>(ptr, array.Length).Fill(value);
}
}
}
} Unsure if it's possible to somehow utilize Would love to see this get added! Edit: Tinkered a bit more and if this does get added to the standard library the non-span path should likely look like this: for (nint i = 0; (nuint)i < array.NativeLength; i++)
{
array.InternalSetValue(value, i);
} A lot better than the lib-external solution! |
Not seeing this mentioned before - as of .NET 6 (courtesy of @GrabYourPitchforks, done in #53562) we now also have a public static void Fill<T>(Array array, T value)
{
// Skipping prologue with checks and whatnot. Also ignoring cases where the size of
// the array exceeds int.MaxValue, feel free to check/chunk if you need to support that.
ref byte reference = ref MemoryMarshal.GetArrayDataReference(array);
Span<T> span = MemoryMarshal.CreateSpan(ref Unsafe.As<byte, T>(ref reference), array.Length);
span.Fill(value);
} Sidenote, if you're using CommunityToolkit.HighPerformance, for the 2D array case you can also just do: public static void Fill<T>(T[,] array, T value)
{
array.AsSpan2D().Fill(value);
} |
The proposed During discussion it was suggested that instead the static methods on Array that take an array as the first parameter should/could be transitioned over to MemoryExtensions (or some other destination) as extension methods, and then having one extension method for |
What about adding an I think that although this would be some amount of work, this would be the best solution for the long term health of the platform, and could help people working with multi-dimensional arrays in other ways as well, not just for one specific API. Such an |
Background and Motivation
First of all, C# provide Multidimensional Arrays structure. It is good that the API like
Array.Copy
can deal with multi-dimensional array well. For example, we can copy one multi-dimensional array to another one easily as below.The usage is like this:
When it comes to
Array.Fill
method, the dimension of input array is specified on only one-dimensional arrayT[]
. I think that it is good to consider to addArray.Fill
overloading methods to handle the multi-dimensional array input, i.e. something likeT[,]
.Proposed API
Similar to the existed
Array.Fill<T>
method, the proposed API is also with two parameters: an array and a value. The first parameter (array input) is a multi-dimensional array. The second parameter (value input) is the value to assign to each array element. An experimental implementation of aArray.Fill
overloading method for two-dimensional array is as follows.An experimental implementation
Usage Examples
Based on the experimental implementation above,
Array.Fill
method can be used like this:Alternative Designs
Another possible design of API form is something more similar to
Array.Copy
. Specifically, make declaration as below.In this form, the array input is more generic than
T[,]
(and the other overloading methods forT[,,]
,T[,,,]
...) and a possible implementation ofvoid Fill(Array array, T value)
method is like below.Risks
Because the proposed
Fill
method is also a kind of generic type API, some exception cases, includingArgumentNullException
andArgumentException
should be considered to make API be more robust.The text was updated successfully, but these errors were encountered: