C#関数で使える引用this、逐語的識別子@、where (テンプレ)について

public static T Func<T>(this MyObject @this) where T : MyComponent

「おわかりいただけただろうか?実はこれ、 C# の関数型として通用するのだ」

Csharp の関数型thisやwhereのイメージ

おわかりいただいた方このページの情報は必要ないけど、暇つぶしに初心者の勉強ノートを見るつもりで読んでください。

TopDown Engine のソースコードを読んでいると、様々な構文が使われていて、とても勉強になります。
ソースコードをそのまま見せるのは多分良くないと思うので、関数・クラス名を変更した関数型だけを冒頭に書きました。

今回は、筆者にとって新たな発見だった以下の

  • 引用 this
  • 逐語的識別子@
  • where (型パラメーターの制約)

を紹介し、冒頭の関数型がどのようなものかを説明します。

おわかりしているはずのところの説明

public

オブジェクトの外部から呼び出して良い関数がつけるアクセス修飾子です。
obj.Greet() みたいな感じで obj の外側から利用できる関数です。
protected, private は obj のクラス定義の中の関数からしか呼び出せない内部で使う関数となります。
public は外部に公開したインターフェースという感じです。

static

静的関数であることを表す修飾子です。
メンバ関数は呼び出し元のオブジェクトを必要としますが、静的関数は呼び出し元のオブジェクトなしで呼び出せます。
念のため確認しました。 参照:static(C#) – 超初心者向けプログラミング入門

T

関数名のあとに<T> とつけるとテンプレート関数になり、そのテンプレート引数名が T です。
別に T ではなくても良いのですが、よく使います。
T には関数呼び出し時にさまざまな型が指定されるので、テンプレート関数ひとつさまざまな型に対応した処理を定義できます。
最初の T は戻り値の型が T であるという意味です。
テンプレート関数を呼び出す際は、T を指定する必要があるので Func<MyClass>() のように関数なの後に型を指定して呼び出します。

引用 this

参照サイトを読んだ所感では、静的関数のシンタックスシュガーです。
シンタックスシュガーは糖衣構文の名前のとおり、構文をわかりやすく表現した別の表現のことです。
引用 this を使った静的メソッドを拡張メソッドと呼びます。

拡張メソッドでは、引用 this の後の型(今回は MyObject ) のメンバ関数のような書き方でその拡張メソッドを呼び出すことができます。

今回の例ならば

MyComponent myComponent = myObject.Func<MyComponent>();

といった形で、実際は MyObject のメンバ関数でもないのに呼び出せます。
当然、実態はそのクラスとは無関係の静的関数のため、そのクラスの内部変数・関数などを扱うことはできません
しかし、関連する静的関数を型・オブジェクトに関連付けられるため、コードを書く際に選びやすくなると思います。

そのクラスのメンバ関数の名前と被った場合は、メンバ関数が優先されるなど他にも様々な説明がありましたが、詳細は以下の参照サイト様をご覧ください。

逐語的識別子@

@逐語的テキストを表現する特殊文字です。
thisfor といった予約語(キーワード)変数名として使えませんが、それを使えるようにするためのエスケープシーケンスのようなものです。
これにより前述の this 引用の引数名@this と書くことができます。
for 文の for も @for とすればただの識別子になります。
「変数名として使いたいのに予約語だから使えない」といった場合に便利です。

他にも path = “path\\to\\file”; などとエスケープシーケンスをつけて書いていたファイルパスを表す文字列などを path = @”path\to\file”; とコピペだけで済む形でエスケープシーケンスなしで記述することができたりします。詳細は以下のサイト様を参照してください。

where (型パラメーターの制約)

where は C# の様々な文脈で使われていて、ケースごとに意味が異なります。
今回は冒頭のテンプレート関数で使われている where について説明します。

テンプレート関数の引数リストのあとの where T : MyComponent は、型引数である TMyComponent基底クラスとしなければいけないという T の条件を表します。

MyComponent クラスやその派生クラスしか型引数として指定できないという意味です。

テンプレート関数に限っただけでも、他にも様々な使われ方がたくさんありました。
そちらについてはこのサイト様を参照ください。

また、where 句として、SQL 文のように配列要素から選別する際に使うこともあります。
そちらについてはこのサイト様を参照ください。

おわかりいただけただろうか?

筆者は C# は奥がとても深いことがわかりました。
いきなり全部を学ぶのは無理そうなので、今回のように知りたいところだけ知っていくスタイルで学ぼうと思います。

public static T Func<T>(this MyObject @this) where T : MyComponent

この呪文のようなテンプレート静的関数は

  • MyObject 型の拡張メソッド
    • メンバ関数ではないけどメンバ関数のように呼び出すことができる。
  • 引数の型 MyObject の前の this は拡張メソッドを宣言するための this 引用
    • this 引用を書くことによって MyObject の拡張メソッドになる。
  • @this はただの引数名
    • this のような予約語(キーワード)を変数として使いたいときは @ を前につける。
  • where は、関数呼び出しで指定するテンプレート引数の型 T の条件指定
    • 今回は戻り値の型 T が MyComponent 派生であることが条件
    • myObject<MyComponent またはその派生型>(); は OK。
    • myObject<MyComponent でもなく派生でもない型>(); は NG。

勉強したばっかりで、説明がおぼつかないですが、???だった数時間前とは違い、普通に冒頭の関数宣言を読むことができるようになりました。
引き続きコードを読みつつ、TopDown Engine のカスタマイズのやり方を学びたいと思います。

参照サイト Thank You!

コメント

Ads Blocker Image Powered by Code Help Pro

お願い - Ads Blocker Detected

このサイトは広告を掲載して運営しています。

ポップアップを閉じて閲覧できますが、よろしければ

このサイト内の広告を非表示にする拡張機能をオフにしていただけませんか?

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

We have detected that you are using extensions to block ads. Please support us by disabling these ads blocker.

タイトルとURLをコピーしました