我只是想知道,有没有更好的方法来初始化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循环并将其替换为单行?那太好了
嵌套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();