首页 > 解决方案 > 如何创建未知多维参数?

问题描述

我想知道是否可以创建一个通用的多维参数。我正在制作一个通用列表/数组洗牌类,它有一个静态方法,它获取一个 IEnumerable 参数并返回相同但已经洗牌。问题是我不知道如何使参数如此通用以至于它可以获得任意数量的维度数组/列表。

先感谢您。

这是我现在写的代码:

 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;
    }

标签: c#genericsmethodsshufflegeneric-method

解决方案


据我所知,没有办法访问任意等级的通用类型多维数组。

备选方案 1:使用无类型数组

Array arr = new int[1,1];
var rank = arr.Rank;
var value = arr.GetValue(0,0);

这样做的缺点是它相当慢,并且会导致一堆拳击。

备选方案 2:使用自定义多维类型

 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
      }
 }

这样做的一个优点是您可以使用泛型类型,并允许直接访问底层数组。缺点是您需要编写一堆数学来将任意等级的索引转换为一维索引。这种情况的一个变体是具有不同的类型,My2DArray、My3DArray 等,以及一个通用接口。

备选方案 3:根据需要定义尽可能多的方法

 public static void MyMethod<T>(T[]) { /*...*/}
 public static void MyMethod<T>(T[,]) { /*...*/}
 public static void MyMethod<T>(T[,,]) { /*...*/}
 public static void MyMethod<T>(T[,,,]) { /*...*/}

这很容易做到并允许通用类型,但需要大量重复代码。

根据我的经验,1d、2d 和 3d 数组是最常见的。我从未见过在野外使用的 4d 数组。甚至 3d 数组也经常变得如此之大,以致于将一维存储为锯齿状数组(即 int[][,])会更好,因为它避免了需要巨大的连续内存块,允许锁定单个切片等。更喜欢使用自定义多维数组类型,因为我发现想要对数据进行线性访问是很常见的,比如序列化或洗牌。


推荐阅读