Reputation: 11
I would Like to know if it is possible to create a generic multidimensional parameter. I am making a generic list/array shuffle class which would have a static method which gets an IEnumerable parameter and returns the same but already shuffled. The Problem is I don't know how to make the parameter so generic that it would get any number of dimensions array/list.
Thank you in advance.
Here is the Code I Wrote For Now:
public static IEnumerable<T> OneDimensionalShuffle<T>(IEnumerable<T> array)
{
var originalList = array.ToList();
var shuffledList = new List<T>();
var rand = new Random();
for (var i = originalList.Count - 1; i >= 0; i--)
{
var randomArrayPosition = rand.Next(i + 1); //i+1 because maxValue is exclusive
shuffledList.Add(originalList[randomArrayPosition]); //Add random point to the shuffledList
originalList.RemoveAt(randomArrayPosition); //Remove element which was already added to shuffledList
}
array = shuffledList;
return array;
}
Upvotes: 0
Views: 107
Reputation: 36649
As far as I know there is no way to access a generic typed multi-dimensional array of arbitrary rank.
Alternative 1: Use a untyped array
Array arr = new int[1,1];
var rank = arr.Rank;
var value = arr.GetValue(0,0);
Downside with this is that it is rather slow, and will cause a bunch of boxing.
Alternative 2: Use a custom multidimensional type
public class MyMultiDimensionalArray<T>{
public T[] backingDataStorage {get;}
public int Rank {get;}
public int[] Length {get;}
public T GetValue(params int[] indices){
// Math to convert the indices to a one dimensional value
}
}
An advantage of this is that you can use generic types, and allow direct access to the underlying array. The downside is that you need to write a bunch of math to convert a index of arbitrary rank to a 1d index. A variant of this is to have different types, My2DArray, My3DArray etc, and a common interface.
Alternative 3: Define as many methods as you need dimensions
public static void MyMethod<T>(T[]) { /*...*/}
public static void MyMethod<T>(T[,]) { /*...*/}
public static void MyMethod<T>(T[,,]) { /*...*/}
public static void MyMethod<T>(T[,,,]) { /*...*/}
this is fairly easy to do and allow generic typing, but will require a bunch of code-duplication.
In my experience 1d, 2d and 3d arrays are most common. I have never seen a 4d array used in the wild. And even 3d arrays can often become so large that it can be better to store one dimension as a jagged array, i.e. int[][,], since it avoids the need for a huge continuous memory block, allow locking individual slices etc. I prefer to use custom multidimensional array types, since I find it quite common to want linear access to the data, for things like serialization, or shuffling.
Upvotes: 1