はじめに
最近になってUnityで開発することが増え、C#に触ることが多くなったので「使ってこれは便利だな」と感じたものをここに備忘録がてらまとめておきます。(主はC++からC#を触ってるのでC++と比較しての視点で書いてます。)
Unity2019.4.0f1時点でのバージョンはC#7.3が標準だそうです。
プロパティ構文
C++ではことあるごとにGetter/Setterを作らないといけなかったがC#ならこのように記述できる。
public class BaseCompornent : MonoBehaviour {
//座標
public Vector3 Position
{
set { transform.position = value; }
get { return transform.position; }
}
public float PosX
{
set
{
Vector3 pos = Position;
pos.x = value;
Position = pos;
}
get { return Position.x; }
}
参照するときはこのようにメソッドを呼び出すことなくメンバ変数のように扱える。
public void Function()
{
PosX += 100;
var posX = posX;
PosX++;
}
Unityでゲーム作ってるとどうしてもクラス間の値の受け渡しが多くなるため、この機能はとても助かる。
ちなみにget/setのどちらかは省略することが可能である。
また自動実装プロパティといって単純に「get; set;」記述することもできる。その際はプロパティ自体がデータを保有することになる。
名前付き引数
良く調べたらこの機能C++ではないそうです。(C#は4.0から実装されたみたい)
簡単に言えば指定した引数だけを渡せれるってやつです。
デフォルト引数と兼ねたコード例です。
public void Function()
{
AddPosition();
AddPosition(15.0f, 25.0f);
AddPosition(1.0f,20.0f, 30.0f);
AddPosition(vy: 30.0f); //指定することが可能
}
public void AddPosition(float vx = 0.0f, float vy = 0.0f, float vz = 0.0f)
{
PosX += vx;
PosY += vy;
PosZ += vz;
}
何気にこの機能最近知ったので、上手いこと使いこなしていきたいですね。
VBには昔からある機能だそうです。
LINQ
最初、LINQとはなんぞやとなりましたが要はC#独自のSQLみたいなやつです。(正式名称は統合言語クエリと呼ぶみたい)
データベース関係に疎いので上手い使い方は出来ていないかもしれませんが、現在開発中のコードではこんな感じで使っています。
private void RemovePort(BaseNode node, Port port)
{
var targetEdge = edges.ToList().Where(x => x.output.portName == port.portName && x.output.node == port.node);
if (targetEdge.Any())
{
var edge = targetEdge.First();
edge.input.Disconnect(edge);
RemoveElement(targetEdge.First());
}
//省略
}
やってることとしては「where」の部分でエッジリストから「エッジの出力ポート名と対象のポートのポート名が同じ かつ 対象ノードと出力先のノードが同じ」という条件のエッジを抽出しています。
そして「Any()」の行で抽出したエッジがあれば if 文内の処理をするようにしています。
指定した条件の要素を抽出したいときに結構使う便利だなと感じます。
リフレクション
この機能もC++には現状ありません。(これぞとばかりにC++に恨みがあるんかって感じですけど)
何が出来るかというと、クラスの情報をデータとして扱えます。(メタデータ)Typeクラスを使って実装します。
コード例も開発のものから引っ張てきました。
public class BaseNode : Node
{
public string Guid;
public Type type;
public bool EntryPoint;
public BaseNode()
{
Guid = System.Guid.NewGuid().ToString();
type = this.GetType();
title = type.Name.Replace("Node", ""); //クラス名から "Node" を削除したもの
EntryPoint = false;
}
まだこれは単純ですが、BaseNodeのメンバにTypeクラスの変数を宣言し、コンストラクタの「GetType()」でBaseNodeクラスをタイプオブジェクトとして格納しています。また文字列としても取得することが出来ます。「type.Name」でクラス名を取得し、"Node"部分を削除してそのままNodeのタイトルとして流用しています。
こうすることでこのBaseNodeクラスを継承したクラスでも機能が働き、子クラスのクラス名を勝手に取得して反映させてくれます。
Typeクラスからインスタンスを生成をすることもできます。詳しくは参考記事をご覧ください。
おわりに
Unityを触ってて便利だなと感じたC#の機能はこんな感じです。(あとの機能はC++にもある機能だったりので省いてます。)
まだ他にも「式木」とかあるんですけど、使いどころがあまりないと感じたので割愛。
もっとこういう使い方あるよとか便利な機能があるよっていうアドバイスがありましたら気軽にコメントしてくれるととても助かります。
参考記事
[C#とC++の比較] (http://flat-leon.hatenablog.com/entry/comparison_between_csharp_and_cpp)
Unityで使える!C#の便利な機能7選
[オプション引数・名前付き引数] (https://ufcpp.net/study/csharp/sp4_optional.html)
[C#のプロパティについて調べてみた] (https://qiita.com/ShirakawaMaru/items/5f8bd065b1a4d2fdc8e0)
[はじめてのLINQ] (https://qiita.com/nskydiving/items/c9c47c1e48ea365f8995#%E8%A6%81%E7%B4%A0%E3%81%AE%E5%8F%96%E5%BE%97)
[C#リフレクションTIPS 55連発] (https://qiita.com/gushwell/items/91436bd1871586f6e663)
[リフレクションを利用して文字列からクラス操作] (https://pknight.hatenablog.com/entry/20130320/1363804675)