在c#中初始化多维数组对象

本文关键字:数组 对象 初始化 | 更新日期: 2023-09-27 18:09:24

我只是想知道,有没有更好的方法来初始化c#多维对象数组(引用类型)

下面是我的代码:
Board = new Field[BoardHeight, BoardWidth];
for (int i = 0; i < BoardHeight; i++)
{
    for (int j = 0; j < BoardWidth; j++)
    {
        Board[i, j] = new Field();
    }
}

如果我可以摆脱for/for循环并将其替换为单行?那太好了

在c#中初始化多维数组对象

嵌套for循环通常是最易读/被接受的初始化2d数组的方法。

如果你真的需要单语句-一个选择是使用Enumerable.Aggregate(创建/填充数组在单语句)和Enumerable.Range + Enumerable.SelectMany(创建索引使用如何我采取笛卡尔连接两个列表在c#?):

 Board = Enumerable.Range(0, BoardHeight)
         .SelectMany(x => Enumerable.Range(0, BoardWidth), (row,col)=>new {row,col})
         .Aggregate(new Field[BoardHeight, BoardWidth],
             (board, position)=> 
               {
                   board[position.row,position.col] = new Field(); 
                   return board;
               });

(这段代码的可读性是开放讨论的)

更实用的解决方案:

for (var i = 0; i < BoardHeight* BoardWidth; i++) 
{
    Board[i / BoardWidth, i % BoardWidth] = new Field();
}

如果你真的需要"单行初始化"——将嵌套的for循环重构成方法(可能是通用的),并在你想要的任何地方用"单行"调用它。比如:

   public TField[,] InitializeArray<TField>(
      int BoardHeight, int BoardWidth) where TField:new()
   {
        var Board = new TField[BoardHeight, BoardWidth];
        for (int i = 0; i < BoardHeight; i++)
        {
            for (int j = 0; j < BoardWidth; j++)
            {
                Board[i, j] = new TField();
            }
        }
        return Board;
}

更多的是出于好奇,我将一些旧代码改编为一个扩展方法,该方法将使用提供的Func的结果初始化任意秩数组的每个成员。您可以这样使用它(2D, 3D,任何d数组):

var board = new Foo[10, 20];
board.Fill(() => new Foo());

下面是扩展方法:

static class Extensions
{
    public static void Fill(this Array arr, Func<object> gen)
    {
        // Get the dimensions of the array
        var dims = Enumerable.Range(0, arr.Rank)
            .Select(arr.GetLength)
            .ToArray();
        Func<int, int, int> product = (i1, i2) => i1 * i2;
        for (var i = 0; i < arr.Length; i++)
        {
            var indices = dims.Select((d, n) => (i/dims.Take(n).Aggregate(1, product))%d).ToArray();
            arr.SetValue(gen(), indices);
        }
    }
}

感谢MarcinJuraszek和Alexei Levenkov的建议,我得出了这个答案。从技术上讲,它不是一个单独的语句(总而言之),但如果您隐藏扩展方法;-),它将看起来非常干净:

Board = new Field[BoardHeight, BoardWidth];
Board.Init();

隐藏:

public static class MyExtensions
{
    public static void Init<T>(this T[,] board) where T : new()
    {
        for (int i = 0; i < board.GetLength(0); i++)
        {
            for (int j = 0; j < board.GetLength(1); j++)
            {
                board[i,j] = new T();
            }
        }
    }
}

我认为这是最简单的一行代码(为了可读性分成多行)来初始化你的数组:

var board = Enumerable.Range(0, BoardWidth)
    .Select(row => Enumerable.Range(0, BoardHeight)
        .Select(value =>new TField())
        .ToArray())
    .ToArray();