しばたテックブログスマートフォン用の表示で見るしばたテックブログPowerShellを中心に気分で書いている技術ブログです。(2018年10月版)PowerShell3年ほど前にblog.shibata.techというエントリを書いたのですが、その後新たに分かったことや新しいバージョンでの変更も発生したため、内容を更新してリライトしました。便利なCountプロパティたとえばコマンドを実行して出力した結果の件数を取得したい場合、([コマンド]).Countとするとその件数を取得することができます。Files配下にあるEXEファイルの総数を取得することができます。Countプロパティを使うと、評価した結果(System.IO.FileInfo[])の要素数を取得することができます。-Recurse).Count815Countプロパティの実体System.Array.Count?このCount、要はコマンドを実行した結果(この場合はSystem.IO.FileInfo[])の要素数を取得しているだけなのですが、しかしながら、.NETの配列(System.Array)にはLengthプロパティはあれどもCountプロパティはありません。それでもPowerShellではCountプロパティを利用することができています。バージョン間の差異この謎めいたCountプロパティはPowerShellのバージョンによってその裏にある実体が異なり、その挙動も異なります。6.0で若干の仕様変更が入り現在に至っています。以降、バージョンごとの実体について触れていきます。2.0までのCountプロパティの実体はSystem.Arrayに追加された型データになります。型データとは.NETの型にPowerShell独自のデータを付与できる機能になります。詳細については牟田口先生の以下のエントリを参照してください。winscript.jp型データの定義が記載されているC:\Windows\System32\WindowsPowerShell\v1.0\types.ps1xmlを見るとCountプロパティは以下の様に定義されており、System.Array.Lengthに対するAliasPropertyとなっていることがわかります。</Type>Get-Memberで空の配列@()のメンバを確認してみるとこんな結果を返します。Lengthこの型データにより本来System.Arrayには存在しないCountプロパティを利用することができます。2.0までのCountプロパティはSystem.Arrayに対するものなので配列以外では使うことができません。以下の様なコードは$nullを返し、配列以外ではCountプロパティが存在しないことがわかります。C:\>配列でないオブジェクトに対してCountプロパティを使いたいときは配列化してやる必要があります。3.0からは配列でないスカラ値や$nullに対してもCountプロパティが使える様に機能が拡張されています。Blogのこの記事で触れられる程度の情報しかなく、機能の実体については謎でした。PowerShellがオープンソースとなったため実際にソースを確認してみたところ、このCountプロパティは動的オブジェクトのメンバーフォールバックとして実装されていることが分かりました。DLRを使った動的オブジェクトとして定義されています。これによりこれまでリフレクションによって行われていたメソッドやプロパティの解決が高速化され、PowerShell全体のパフォーマンス改善につながっています。DLRでは、主にエラーハンドリングのために、メソッドやプロパティの解決に失敗したときの処理を定義するフォールバック機能が提供されており、Countプロパティにおいては、オブジェクトのCount(またはLength)プロパティを取得しようとするCount(またはLength)プロパティが存在しないオブジェクトの場合、DLRのフォールバック(FallbackGetMember)が呼び出されるフォールバック処理内で元のオブジェクトの種類に応じて1または0を返すといった動作をしています。(これがすべてではありませんが)ソースコードとしてはこのあたりの処理が参考になります。参考として以下にフォールバックの一部を列挙しておきます。・・・}ちなみに配列に対しては従来通り型データによるAliasPropertyが使われています。3.0で配列以外にもCountプロパティが使える様になったのですが、ぎたぱそ先生の以下のエントリによるとPScustomObjectに対してはCountプロパティは$nullを返してしまいます。tech.guitarrapc.com実際に試してみると確かに$nullを返します。C:\>このためPScustomObjectに対してCountプロパティを使用する際は注意が必要です。6.0においてもCountプロパティの実体が動的オブジェクトのメンバーフォールバックであることは変わらないのですが、いくつか挙動が変更されています。6.0で削除されました。理由としてはこのAliasPropertyが無くても問題がない*1点と、ConvertTo-Json等の処理で不要なCountプロパティが露出してしまう問題(#3222)があったため削除されています。6.1で挙動が改善されPScustomObjectでもCountプロパティが取得できる様に改善されています。4.0のWhere、ForEachメソッドについて最後にちょっとだけおまけを。4.0から配列などのコレクションオブジェクトに対してWhere()およびForEach()メソッドが使える様に機能拡張されています。2})246これらのメソッドも動的オブジェクトのメンバーフォールバックとして実装されいます。ソースコードとしてはこのあたりが参考になると思いますので興味のある方はご覧ください。広告スターをつけました引用をストックしましたストック一覧を見る閉じる引用するにはまずログインしてくださいログイン閉じる引用をストックできませんでした。再度お試しください閉じる限定公開記事のため引用できません。