2019-12-24Unityプログラマにオススメの新しいC#の機能sellC#,.NET,UnityUnityでも新しいC#!長い歴史を持つプログラミング言語、C#。C#は着実に進化し、便利な言語機能を追加してきました。ところがゲームエンジンUnityでは少し前まで、古いC#しか使うことができませんでした。Equivalent」がExperimentalとして選べるようになりました。Equivalent」がExperimentalでなく、安定版になりました。Equivalent」が非推奨になりました。7.3を使うことができます。(投稿執筆時の最新C#は8.0)ところで、Unityプログラマの方の中には「こんなC#の機能があるのか!」と驚く人や、「新しいC#の機能、わからない」と困っている人もいるのではないでしょうか?この投稿では、Unityでのロジック記述でオススメの新しいC#の言語機能を、筆者の独断と偏見で紹介します。プロパティの書き方いろいろ次のコードはUnityでよく使うプロパティの例です。ゲッターオンリーのプロパティで、SerializeFieldがついたフィールドをバッキングフィールドとしてもっています。}}}新しいC#では次のように、=>を使って短く書けます。hp;}冗長な部分のコードがなくなり、コードが短く簡潔になったことに注目してください。次のコードは、古いC#におけるセッター・ゲッター両方をもつプロパティの例です。}}これらも=>を使って冗長な部分を取り除き、簡潔に記述することができます。}}C#にはもともと自動実装プロパティという機能がありました。自動実装プロパティは、バッキングフィールドを自分で書かなくてよいプロパティです。}}古いC#では自動実装プロパティが使えない場面がいくつかありました。新しいC#では、自動実装プロパティが使える場面が増えています。次のコードではreadonlyなフィールドをバッキングフィールドとしてもつNameプロパティです。参照を設定しそれを書き換えない」というプロパティを実現するためには、このように書く必要がありました。自動実装プロパティは使えなかったのです。}}新しいC#では、このようにreadonlyなプロパティを自動実装プロパティのみで簡潔に実現できます。}}次のコードは、バッキングフィールドに初期値をフィールド初期化子で設定しているプロパティです。古いC#ではプロパティの初期値を設定するためには、このように書く必要がありました。自動実装プロパティは使えなかったのです。}}新しいC#では、初期値の設定とともに自動実装プロパティが使える。Name";}新しく加わった機能は便利機能ばかりですが、注意しないといけない機能もあります。新しいC#では、自動実装プロパティのバッキングフィールドに属性をつけられるようになりました。この機能を使い、SerializeFieldをプロパティのバッキングフィールドに付けたくなります。残念ながらこれは期待する挙動になりません。インスペクターに出てこない)「自動実装プロパティのバッキングフィールドに属性付与」と「SerializeField」は合わせて使わないようにしてください。}}新しいプロパティは、コードの設計が劇的に変わるわけではありませんが、コードが簡潔になります。複数の値を返したい時・まとめたい時はValueTupleメソッドで複数の値を返したい時、どうすればいいでしょうか?クラスか構造体を作ればいいでしょうか?ValueTupleは、クラスや構造体などの型を定義しなくても、複数の値をまとめることができるデータ型です。これを使えば、メソッドで複数の値を簡単に返すことができます。ToStringや、HashCode、Equals、==での比較も実装されており、データ処理時にとても活躍します。新しいC#では、ぜひValueTupleを使ってみてください。ValueTupleは、非常に扱いやすい形で複数の値をまとめることができる構造体です。ValueTupleは、つぎのように()や要素名を記述し、生成することができます。31);上で作ったValueTupleには、nameとlevelというメンバがあります。{person0.level}");メソッドの返値型としてValueTupleを使う時は、このように書きます。31);ToStringやHashCode、Equalsや==も実装されています。person1);Debug.Log(person0.name);Debug.Log(person0.level);Debug.Log(person0.ToString());ValueTupleを扱う際分解を使うと、非常に簡潔にかけます。LoadNameAndLevel();}今までの古いC#でも、匿名型という便利な言語機能がありました匿名型もクラスや構造体を定義しなくても、名前のない型を作れる機能です。詳しくはこちら「C#の匿名型について調べてみた」。匿名型は、LINQやRxなどの処理の中間データとしては非常に便利だったのですが、メソッドの返り値型にできませんでした。ValueTupleはメソッドの返値型にできます。ValueTuple構造体よりも前、クラス型のTupleがありました。Tupleを使えば複数の値をまとめることはできました。メンバの名前がItem1やItem2となっていること、構造体ではなくクラスであったことなど、あまり使い安くありませんでした。「privateメソッドで複数の値をまとめて返したい。型を作るほどではない」という場面があると思います。そのような時は、ぜひValueTupleを活用してください。ValueTupleは便利ですが、型を作るべき場面もあります。使いすぎに注意してください。ValueTupleを活用したライブラリ、ImportedLinqもみてみてください。protected今までのC#のアクセスレベルは次のものがありました。protectedが加わりました。Filesが使えるようになり、アセンブリを意識して開発する機会が増えました。今までのUnityにおけるアクセスレベルでは、次の3個を使うことが多かったです。Filesにより、Unityでも簡単にアセンブリを分割できるようになりました。これにより、「アセンブリ内に閉じる」ということが大事になりました。internalアクセス修飾子を使えば、同一アセンブリ内のみにアクセスを制限できるようになりました。Filesとともに活用してください。internalは「同一アセンブリ」もしくは「その型とその派生型」のどちらかであればアクセスできるアクセスレベルです。protectedは「同一アセンブリ」かつ「その型とその派生型」がアクセスできるアクセスレベルです。Filesが使えるようになり、アセンブリを意識して開発する機会が増えました。protectedアクセスレベルを活用してください。でかい〜」も参照してください。nullの扱いもやりやすく「null参照の発明は10億ドルにも相当する誤りだった」という言葉もありますが、C#にはnullがあります。nullと上手につきあっていかないといけません。新しいC#では、そんなnullを上手に扱える記法が追加されています。次のようなMonsterクラスとPlayerクラスがあります。}}MonsterのNameプロパティもPlayerのTargetプロパティもnullになりえます。そこで次のように三項演算子とnull判定を使って、次のようなコードを書く必要があります。本当にやりたいことは、メンバへのアクセスだけなのに、非常に冗長です。null;新しいC#ではこのように?.を使って非常に簡潔に記述できます。player?.Target?.Name;「もし対象がnullだったら指定した既定の値を設定したい」という状況があると思います。古いC#では次のような書き方をする必要がありました。Name";新しいC#ではこのように??を使って非常に簡潔に記述できます。player.Target」は等価ではありません。==をその型が実装している時は注意してください。?.や??を使う場合、==は呼ばれません。?.や??は非常に便利ですが、UnityのGameObjectやMonoBehaviourの中で使うには注意が必要です。Unityにおいて、GameObjectやコンポーネントでは、?.や??には注意が必要です。GameObjectやコンポーネントでは==が実装されています。?.や??を使った際に、何が起こるか考えてみてください。person.Name」は等価じゃない。(JetBrains/resharper-unityのwiki)進化したSwitchプログラミング言語C#を学び始めた時、ほとんど全ての人はswitchを勉強したと思います。新しいC#では、switchはとても強化されています。今までのC#でのswitch文では、列挙型の値、数値の値、文字列の値で分岐するだけでした。次のコードのようにです。}}新しいC#では型で分岐できるようになりました。次のようなことができるようになったのです。}}より具体的で実用的なコードだとこのようなことができるようになりました。Math.PI;}Shape型を継承したRect型とCircle型があります。これとswitchを使って、次のようなコードを書くことができます。8.0でさらに進化しています。今後のC#でさらに強くなっていくでしょう。ダメージ計算、特定計算などで活躍すること間違いなしです。今後の強化にも期待しましょう。Coreの躍進により、よりいろいろな領域で活躍するようになりました。領域が広がったことにより、パフォーマンスを求められることも増えてきました。新しいC#では、パフォーマンス改善で活躍する多くの機能が追加されました。Things」というとても素晴らしい公演を参照してください。まとめC#は着実に進化し便利な言語機能を追加してきました。今までUnityでは古いC#しか使えませんでしたが、最近新しいC#が使えるようになりました。Unityプログラマの方に使って欲しい新しいC#の機能がたくさんあります!この投稿では、Unityでのロジック記述でオススメの新しいC#の言語機能を、筆者の独断と偏見で紹介しました。この投稿で紹介していない、便利な新しいC#の機能もたくさんあります。次の公式ドキュメントや、ufcppさんのとてもわかりやすいブログでぜひ調べてみてください。