C#の場合、LINQの拡張メソッド機能を使用して簡単にコードを記述できる
Example.cs
using System.Collections.Generic;
using System.Linq;
namespace ConsoleApp1 {
class Program {
static void Main(string[] args) {
//実際に使用できる
List<int> list = Enumerable.Range(0, 10).Where(i => i % 2 == 0).Select(i => i * 2).ToList();
}
}
}
ところが、powershellの場合(5.0以降であっても)拡張メソッドを使用することはできない
Example.ps1
#このような式は使用できない
[List[int]]$list = [Enumerable]::Range(0,10).Where({ $args[0] % 2 -eq 0 }).Select({ $args[0] * 2 }).ToList();
#解決策1:拡張メソッドとしてではなく、通常のstaticメソッドとしてLINQを使用する
Example.ps1
using namespace System.Collections.Generic;
using namespace System.Linq;
#powershell5.0以降であれば、usingを使用できる。
#使用できない場合は、[System.Linq.Enumerable]とする。余計長くなってしまう。
[List[int]]$list = [Enumerable]::ToList([Enumerable]::Select([Enumerable]::Where([Enumerable]::Range(0,10),[Func[int,bool]]{ $args[0] -eq 2 }),[Func[int,int]]{ $args[0] * 2 }));
#解決策2:拡張メソッド風のクラスを宣言して疑似的にLINQにする
Example.ps1
using namespace System.Collections.Generic;
using namespace System.Linq;
#型宣言部分。記述量全体でいうと、かえって増えてしまう
class E
{
[IEnumerable[int]]$inner;
E([IEnumerable[int]]$x){
$this.inner = $x;
}
static [E] Range([int]$x,[int]$y){
[E]$r = [E]::New([Enumerable]::Range($x,$y));
return $r;
}
[E]Where([Func[int,bool]]$y){
$this.inner = [Enumerable]::Where($this.inner,$y);
return $this;
}
[E]Select([Func[int,int]]$y){
$this.inner = [Enumerable]::Select($this.inner,$y);
return $this;
}
[List[int]]ToList(){
return [Enumerable]::ToList($this.inner);
}
}
#本体部分。本体はLINQのように短く記述できるが、単純にパイプのほうが効果的かもしれない
[List[int]]$list = [E]::Range(0,10).Where({ $args[0] % 2 -eq 0 }).Select({ $args[0] * 2 }).ToList();