SelectMany があればいいんじゃないだろうか?
2次元配列を扱うのに、もう2重ループは必要ありませんね。
SelectManyと2次元配列の素敵な関係:Gushwell's C# Dev Notes
というのを読んで、むしろ LINQ っぽく扱えた方がうれしいんじゃないかな、と言うことで書いてみた。
static class Program { static IEnumerable<S> SelectMany<T, S>(this T[,] self, Func<T, int, int, IEnumerable<S>> f) { for (int i = 0; i < self.GetLength(0); i++) for (int j = 0; j < self.GetLength(1); j++) foreach (var t in f(self[i, j], i, j)) yield return t; } static IEnumerable<S> SelectMany<T, S>(this T[,] self, Func<T, IEnumerable<S>> f) { return self.SelectMany((t, _, __) => f(t)); } static void Main(string[] args) { int[,] nums = new int[,] { {13, 200,31, 43, 54 }, {110,20, 330,410,50}, {100,220,33, 40, 500} }; foreach (var t in nums.SelectMany(t => new[] { t })) Console.WriteLine(t); } }
これなら i とか j とかが欲しい場合でも、(t, i, j) => ... と受け取れるし。
Select も用意して、new[] { t } すらいらなくしてもいいかも。
追記。T4 ってみた。
<#@ template debug="true" hostSpecific="true" #> <#@ output extension=".cs" #> <#@ Assembly Name="System.Core.dll" #> <#@ Assembly Name="System.Windows.Forms.dll" #> <#@ import namespace="System" #> <#@ import namespace="System.IO" #> <#@ import namespace="System.Diagnostics" #> <#@ import namespace="System.Linq" #> <#@ import namespace="System.Collections" #> <#@ import namespace="System.Collections.Generic" #> <# int n = 10; #> using System; using System.Collections.Generic; public static class Linq { <# for (int dim = 2; dim <= n; dim++) { #> public static IEnumerable<S> SelectMany<S, T>(this T[<#= new string(',', dim - 1) #>] self, Func<T, <#= Seq("int", ", ", 0, dim) #>, IEnumerable<S>> f) { <# for (int i = 0; i < dim; i++) { #> for (int i<#= i #> = 0; i<#= i #> < self.GetLength(<#= i #>); i<#= i #>++) <# } #> foreach (var t in f(self[<#= Seq("i{0}", ", ", 0, dim) #>], <#= Seq("i{0}", ", ", 0, dim) #>)) yield return t; } public static IEnumerable<S> SelectMany<S, T>(this T[<#= new string(',', dim - 1) #>] self, Func<T, IEnumerable<S>> f) { return self.SelectMany((t, <#= Seq("_{0}", ", ", 0, dim) #>) => f(t)); } <# } #> } <#+ string Seq(string template, string sep, int begin, int end) { return string.Join(sep, Enumerable.Range(begin, end - begin).Select(i => string.Format(template, i))); } #>
おー、これはよいかも?