Movatterモバイル変換


[0]ホーム

URL:


UnityC#のLinq・属性・拡張メソッド・クラスの部分定義の使い方

C#の色々な機能についての画像Unity C#入門講座
今回の記事ではC#の色々な機能について見ていきます。


Unity入門の森オリジナル本格ゲーム制作講座はこちら
11種類の本格ゲームの全ソースコード公開・画像&動画による解説付き

今回の記事では拡張メソッド、Linq、属性、クラスの部分定義など開発にとても役立つC#の機能を説明します。

前回のデリゲートとイベントはちょっと難易度が高かったですが、今回の記事はもう少し取り組みやすくなります。ぜひ読んでみてください。

前回の記事:

UnityC# デリゲートとイベントとUnityActionの使い方
今回の記事ではデリゲートとイベントについて解説していきます。前回は辞書の使い方について解説しましたね。デリゲートとイベントを使うことでメソッドを値として使用することができます。メソッドを値にして利点があるのかと思われますが、アプリでできるこ...
feynman.co.jp
2023.04.22

【Line登録者限定のプレゼントもあるよ!】

C#の便利な応用機能を紹介

ここまでの記事でC#の基本的な機能については大体解説し終えました。

今回の記事では次の機能について解説していきます。

  • Linq
  • 属性(Attribute)
  • 拡張メソッド
  • クラスの部分定義

Linqとは

Linqとはの画像

Linqはコレクションから要素を取り出すクエリ操作を行うための機能。

Linqとはコレクションから要素を取り出すクエリ(Query)操作を行うC#の機能になります。対応するコレクションにはXMLやSystem.IEnumerableを継承したクラスなどになります。

Linqという名前はLanguage-Integrated Query (LINQ)から来ています。

クエリ操作にはデータベースのクエリ構文と似たようなキーワードを使用します。そのためコレクションの要素を簡単に取り出すことができ、さらにループ文で書くより読みやすく理解しやすいものとなります。

そのため、コレクションから要素を取り出したい時は基本的にLinqを利用するといいでしょう!

Linqはかなり多機能な機能になりますのでここでは簡単に紹介するだけに留めておきます。

また、Linqはキーワード形式とメソッド形式の二通りの書き方があります。

キーワード形式では主要なLinqの機能だけ使用できます。そのためLinqの全ての機能を使用できませんので注意してください。

メソッド形式はメソッドをつなげて処理を書いていくことからメソッドチェーンと呼ばれたりします。また、メソッド形式では処理をラムダ関数で定義すると便利です。

Linqの書き方
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
usingSystem.Linq;
usingSystem.Collections.Generic;
 
int[]list=newint[]{0,1,2,3,4,5};
{//キーワードを使ったもの
  //queryにはlistの中の0, 2, 4にアクセスできる。
  IEnumerable<int>query=
    fromvalueinlist
      where0==(value%2)
      selectvalue;
}
{//メソッド形式
  //queryにはlistの中の0, 2, 4にアクセスできる。
  IEnumerable<int>query=
    list.Where(_v=>0==(_v%2));
}

Linqのキーワードについて

Linqでは以下のキーワードが用意されています。これらを組み合わせてコレクションから要素を取り出したりできます。

キーワードメソッド形式概要
fromなしコレクションから取り出す要素の名前を指定する。
whereWhere()条件式で要素をフィルタリングする。trueならその要素を使用する。
selectSelect()クエリ操作の結果最終的に使用する値を指定する。
groupGroupBy()要素を条件式でグループ化する。
orderOrderBy要素をソートする。
joinJoin(),GroupJoin()2つのコレクションを組み合わせてクエリしたい時に使用する。
letなしクエリ式の中で使用する一時的な変数を定義する。

(※実際にはこれ以外のキーワードも使用していますが、主要なものだけ紹介しています。)

(※メソッド形式で「なし」のものは、C#の文法で代替できます。)

Linqのサンプル

Linqはコレクション操作を簡単に行うためのものですが、一部のキーワードについては使い方がわかりづらいものもあります。ここでは簡単なサンプルを用意したので参考にしてください。

基本形

Linqの基本的な使い方
C#
1
2
3
4
5
6
7
8
9
10
11
usingSystem.Linq;
 
varlist=newList<int>(){0,1,2,3,4,5};
 
// 次のクエリ文ではqueryに {3, 4, 5}が入る
varquery=fromnuminlist// <- listの要素をnumという名前で操作していく
  wherenum>2// <- numが2より大きいものをフィルタリングする
  selectnum;// <- numをクエリの出力として使用する
 
//メソッド形式では次のようになる
varquery2=list.Where(num=>num>2);

Group

コレクションの要素を指定した条件式でまとめるクエリ文になります。

  • キーワード形式:group <使用する要素の値> by <条件式>
  • メソッド形式:GroupBy(<条件式>, <グループ化時に使用する値のセレクタ>)
groupの使い方
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
usingSystem.Linq;
 
varlist=newList<int>{0,1,2,3,4,5};
 
//listの要素を偶数か奇数かでグループ化する。
varquery=fromnuminlist
  //numを使用してグループ化する
  // byキーワードの後にグループ化の条件式を書く。
  groupnumby0==(num%2);
 
//メソッド形式
varquery2=list.GroupBy(
  num=>0==(num%2),// <- グループ化の条件式
  num=>num);//<- 要素の値をそのまま使用する
 
//クエリ結果を使用する例
foreach(vargroupinquery){
  group.Key;// <- グループ化の時に使用した条件式の結果が入る。
  //グループ化した値を見る時はgroupをforeachに渡す
  foreach(varnumingroup){}
}

Join

2つのコレクションの要素を見て、指定した条件式が一致するものをまとめる時に使用するクエリ文になります。

Joinには通常のものとinto文を追加したものがあります。

  • 通常のもの:コレクションの要素を1対1でまとめます。
  • into文:コレクションの要素を1対多と片方のものをグループ化してまとめます。

書き方は次のようになります。

  • 通常のもの:join <要素名> in <コレクション> on <既に見ているコレクションの要素の値> equals <要素名の値>
  • into文:join <要素名> in <コレクション> on <既に見ているコレクションの要素の値> equals <要素名の値> into <グループ化した時の名前>

メソッド形式では次のものがあります。

  • 通常のもの:Join(<組み合わせるコレクション>, <<既存のコレクションの要素の値>, <組み合わせるコレクションの要素の値>, <ペアにする時のセレクタ>)
  • into文:GroupJoin(<組み合わせるコレクション>, <既存のコレクションの要素の値>, <組み合わせるコレクションの要素の値>, <グループ化時に使用する値のセレクタ>)
joinの使い方
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
usingSystem.Linq;
 
//Houseに住んでいるPersonをLinqで調べるサンプルコード
classPerson{
  publicintID{get;set;}
  publicstringName{get;set;}
}
classHouse{
  publicintPersonID{get;set;}
  publicstringAddress{get;set;}
}
 
varpersonList=newList<Person>(){
  newPerson(){ID=0,Name="Tom"},
  newPerson(){ID=0,Name="Kumi"},
  newPerson(){ID=0,Name="Mei"},
 
  newPerson(){ID=1,Name="Ken"},
  newPerson(){ID=1,Name="Sara"},
};
 
varhouseList=newList<House>(){
  newHouse(){PersonID=0,Address="Apple"},
  newHouse(){PersonID=1,Address="Microsoft"},
};
 
//同じHouseに住んでいるPersonを調べるクエリ文
varquery=fromhouseinhouseList// <- houseListの要素をhouseに設定する
  //join文 personListも一緒に調べている
  // personListの要素をpersonに設定していて、
  // house.PersonIDとperson.IDが同じpersonをpersonGroupにまとめている
  joinpersoninpersonListonhouse.PersonIDequalsperson.IDintopersonGroup
  // クエリ結果を指定している。
  selectnew{House:house,PersonGroup:personGroup};
 
//メソッド形式
varquery2=houseList
  .GroupJoin(personList,//<- 組み合わせるコレクション。
    house=>house.PersonID,//<- houseListの要素をそのまま使用している。
    person=>person.ID,//<-personListの要素をそのまま使用している。
    //第2,3引数の値が一致するものが引数として渡される。
    // houseはhouseListの要素が、personGroupには一致したpersonListの要素がまとめられている。
    (house,personGroup)=>(House:house,PersonGroup:personGroup));
 
//クエリ結果を使用する例
//queryには次のような感じのデータが入っています。
// {houseList[0], { personList[0], personList[1], personList[2] } }
// {houseList[1], { personList[3], personList[4] } }
foreach(varpairinquery){
  // pair.House // <-House
  // pair.PersonGroup // <- HouseにいるPersonのコレクション
}

属性(Attribute)とは

属性とはの画像

属性はクラスやメンバなどに付加的な情報(メタデータ)を付けることができる機能。

属性(Attribute)はクラスおよびメンバなどのC#の要素に対して付加的な情報(メタデータ、Metadata)を指定できる機能になります。これまでの記事でも既にいくつか使用しています。

書き方としてはクラス・メンバ宣言の前に角括弧[]で括った中に指定したい属性を書いていきます。

書き方:[<属性名>( <引数>... )]

属性にはその定義の際に指定できる種類が設定されています。指定できる種類は大体のC#の要素になります。

  • クラス
  • フィールド
  • メソッド
  • プロパティ
  • イベント
  • 列挙型

UnityやC#には既に定義されている属性がありますのでそちらを利用することもできます。これらの属性を使用するとその属性に対応しているクラスで何かしらの恩恵を受けたり、UnityではInspector上のUIが変更されたりします。

  • RangeAttribute:指定したものが数値型の場合、Inspector上では指定した範囲内でしか値を変更できなくする。
  • MinAttribute:指定したものが数値型の場合、Inspector上では指定した値より下回らないようにする。
  • SerializeFieldAttribute:指定したメンバをUnityのシリアライズ(オブジェクトをデータ出力してファイル保存することをシリアライズという)対象にする。Inpectorでも編集できるようにする時に使用する。

などなど。

属性の指定の仕方。
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
usingUnityEngine;
 
publicSample:MonoBehaviour{
  //属性はクラス定義やメンバ定義の前に書く
  [Range(0f,100f)]
  publicfloatValue;
 
  //複数指定することも可能
  [SerializeField]
  [Min(-10)]
  int_int;
  //下のように,で区切ってもOK
  //[SerializeField, Min(-10)]
  // int _value2;
  // ...
}
属性を指定した時のInspectorのUIについての画像

Unityでは指定した属性によってはInspector上のUIが変更されるものがある。

新しい属性を定義する時の注意点

新しい属性をこちらから定義することももちろん可能です。

定義する際はSystem.Attributeを継承してください。

その際定義する属性の情報を指定する必要があり、それにはSystem.AttributeUsageAttribute属性を使用してください。

AttributeUsageAttributeに渡すことができるパラメータは次のものです。

  • 第1引数:指定できる対象についてのフラグ(System.AttributeTargets)
  • Inherited::派生した先でも影響を与えるかどうか?
  • AllowMultiple:複数指定できるかどうか?
属性の定義の書き方
C#
1
2
3
4
5
6
7
usingSystem;
 
[AttributeUsage(AttributeTargets.All,Inherited=false,AllowMultiple=true)]
publicclassMyAttribute:Attribute{
  publicintProp{get;set;}
  publicMyAttribute(intprop){...}
}

属性を定義するだけならクラス定義とほぼ同じですが、それを利用するアプリを開発したい時はリフレクションという型情報を調べるC#の機能を利用する必要があります。

リフレクションの機能についてはまた別の記事で解説していきたいと思います。

拡張メソッドとは

拡張メソッドとはの画像

拡張メソッドは既に定義されているクラスに対してメソッドを追加する機能。

拡張メソッドは既に定義されたクラス・構造体に対してメソッドを追加定義する機能になります。

拡張メソッドを利用することで既にあるクラスの機能を拡張できたり、よく使う処理をまとめたりすることができます。継承を使わずに元あるクラスに機能追加できるのがミソですね。

拡張メソッドを定義する時は必ず、以下の条件を守る必要があります。

  • static指定されたクラスの中で定義する。
  • 静的メソッドとして定義する。
  • 第一引数には「this <型名> <引数名>」と初めにthisキーワードを書く必要がある

拡張メソッドは拡張対象のクラス・構造体のメンバではありません。そのため、使用できるメンバはpublicなど他のクラスからでも使用できるメンバのみになるので注意してください(privateメンバにアクセスできない)。

拡張メソッドの書き方。
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
publicclassA{
  publicintValue;
}
 
//拡張メソッドはstatic指定されたクラスの中のみ定義できる。
publicstaticclassExtensions
{
  //拡張メソッドは静的なメソッドとして定義するので、
  // 対象となるクラスからアクセスできるメンバのみ使用できる。
  publicstaticintGetValue(thisAinst){returninst.Value;}
}
 
varinst=newA();
inst.Value=100;
varn=inst.GetValue();// <- n == 100

クラスの部分定義とは

クラスの部分定義とはの画像

クラスの部分定義はクラス定義を複数の場所で行える機能。

クラスの部分定義はクラス定義を複数のクラスで行う時に使用する機能になります。主にC#のFormアプリケーションを作る時に使用されています。

クラスの部分定義を使用したい時は必ずpartialキーワードをクラスに指定する必要があります。

書き方:partial class <クラス名>

クラスの部分定義の書き方
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
//クラスの部分定義を行いたいクラスには必ずpartialを指定する。
partialclassA{
  publicintValue;
}
 
//クラスの部分定義は他のファイルにあってもできる。
partialclassA{
  publicintAddValue(intadd)=>Value+add;
}
 
varinst=newA();
inst.Value=100;
varn=inst.AddValue(2);// <- n == 102

まとめ

今回の記事ではC#の便利な機能についてみてきました。

簡単にまとめますと以下のようになります。

  • Linqはコレクションに対するクエリ(Query)操作のこと
  • Linqを使うことでコレクションの要素をデータベース的に検索することができる。
  • 属性はクラスやメンバにつけることができる付加的な情報を表す。
  • 属性を利用したプログラムを作る時はリフレクションという型情報を調べるC#の機能を利用する必要がある。
  • 拡張メソッドはあるクラスにメソッドを追加するC#の機能
  • 拡張メソッドを定義するクラスはstaticを指定する必要がある。
  • 拡張メソッドから使用できるクラスのメンバは静的メソッドからアクセスできるもののみになる。
  • クラスの部分定義はクラスの定義を2つ以上の場所で行うことができる機能。
  • クラスの部分定義では複数のファイルで行ってもいい。
  • クラスの部分定義を行いたい時はクラスに必ずpartialを指定する必要がある。

それでは次の記事に行ってみましょう!

Unity C#のIEnumerable・IEnumeratorとコルーチンの使い方・作り方
今回の記事ではコレクションに関係するIEnumearbleとIEnumeratorについて解説していきます。IEnumerableおよびIEnumeratorはコレクションの要素を取り出す操作を一般化したものになります。少し理解しづらいかも...
feynman.co.jp
2023.04.22

初心者向けUnityC#入門講座に戻る>>



Unity入門の森オリジナル本格ゲーム制作講座はこちら
11種類の本格ゲームの全ソースコード公開・画像&動画による解説付き

関連記事

Unity C#入門講座

Unity C#の文字列と文字列処理メソッドの使い方

今回の記事では文字列について解説していきます。文字列を使えるようになると、アプリ上でテキストを表示できるようになります。ゲーム内でメニュー画面の文字表示やダイアログメッセージを出したりする場合に必須ですね。またそんな文字列を操作する文字列メ...
2023.03.07
Unity C#入門講座
Unity C#入門講座

UnityC# デリゲートとイベントとUnityActionの使い方

今回の記事ではデリゲートとイベントについて解説していきます。前回は辞書の使い方について解説しましたね。デリゲートとイベントを使うことでメソッドを値として使用することができます。メソッドを値にして利点があるのかと思われますが、アプリでできるこ...
2023.04.22
Unity C#入門講座
Unity C#入門講座

UnityC#のインターフェースの使い方・ポリモーフィズムの考え方

今回の記事ではオブジェクト指向の重要な機能であるインターフェースとポリモーフィズムについて解説していきます。インターフェイスを使いこなせるようになるとプログラム全体の管理がしやすくなります。また、Unityなどフレームワークやライブラリはイ...
2021.09.11
Unity C#入門講座
Unity C#入門講座

UnityC# Listの使い方

前回はインターフェースとポリモーフィズムについて学びましたが、今回の記事ではListについて解説していきます。前回の記事:Listは配列をより使いやすくしたコレクションの一つになります。配列より便利なListクラスとはListクラスは配列と...
2021.09.11
Unity C#入門講座
Unity C#入門講座

Unity C#の条件分岐の使い方 if文・switch文

今回の記事では制御文について解説していきます。制御文にはいくつか分類があるのですが、ここでは条件分岐と呼ばれるif文とswitch文について見ていきます。前回の記事:制御文と条件分岐について制御文とはプログラムの処理を実行するかしないかを制...
2021.09.11
Unity C#入門講座
Unity C#入門講座

Unity C#の演算子の使い方をマスターしよう

今回の記事では演算子について解説していきます。演算子は簡単に言うと、足し算、掛け算、引き算、割り算などを意味する記号ですね。プログラミングする上ではこうした四則演算以外でも演算子を利用することがあります。以前の記事の中でも既にいくつか使用さ...
2023.03.06
Unity C#入門講座

コメント

コメントをどうぞコメントをキャンセル

メールアドレスが公開されることはありません。

CAPTCHA


↓知りたいことを検索してね

Unity入門の森 インディーゲームリリース!

魔女と召喚獣

 

Seeker of Darkness

 

呪術迷宮をリリース

unity入門の森 ゲームの作り方のyoutubeチャンネル

unity入門の森 ゲームの作り方
「unity入門の森 ゲームの作り方」のyoutubeチャンネル。unityを用いたゲームプログラミング、unityスクール、ゲームクリエイターになりたい方向けの情報を中心に発信。インディーゲームクリエイター・プロゲーマー・ゲーム実況者を目...
www.youtube.com

ブログランキング参加中(クリックして応援してくれると嬉しいな)

にほんブログ村 教育ブログ プログラミング教育へ
にほんブログ村

カテゴリー

最近の投稿

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

[8]ページ先頭

©2009-2025 Movatter.jp