今回の記事では制御文について解説していきます。
制御文にはいくつか分類があるのですが、ここでは条件分岐と呼ばれるif
文とswitch
文について見ていきます。
前回の記事:
制御文と条件分岐について
制御文とはプログラムの処理を実行するかしないかを制御するための構文になります。
その中でも今回説明する以下の条件分岐は最も基本的な制御文になります。
if
文if else
文?演算子
switch
文
これらの制御文はC#以外のプログラミング言語でも使われており、基本的に同じように使うことができます。
一度使い方を覚えると一生使える知識になるのでがんばっていきましょう!
if文とは
if
文、if else
文は最も基本的な制御文になります。
if文は条件式の中の条件を満たしているとき、満たしていないときで処理を分岐させるために使います。
if文の書き方
if文の書き方は以下のものになります。条件式がtrue(真)
になる時のみ鍵括弧({}
)で括った処理を実行します。
if (<条件式>) { <条件式がtrueの時に実行したい処理> }
1 2 3 4 5 6 7 8 9 10 |
int a = 0; if (2 < 4) { // <- 条件式 2が4より小さい時はtrueになる。 //条件式がtrueの時に実行される処理 a = 100; } int b = -1; if(a == 0) { b *= -1; } |
ちなみに処理が1文に収まる時は鍵括弧を省略することができます。
1 2 3 4 |
int a = 0; int b = 0; // 鉤括弧を省略したもの if (a == 0) b = 100; |
if else文の書き方
if else
文はif
文を拡張したもので、条件式の値によって処理を2つ以上に分岐させることができます。
こちらの場合でも処理が1つに収まる時は鉤括弧を省略することができます。
if (<条件式>) { <条件式がtrueの時の処理> } else { <falseの時の処理> }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
int a; if (2 < 4) { // <- 条件式 2が4より小さい時はtrueになる。 //条件式がtrueの時に実行される処理 a = 100; } else { //条件式がfalseの時に実行される処理 a = 0 } int b = -1; if(a == 0) { //aの値が0かどうかで処理を分岐させる // a == 0の時に実行される処理 b *= -1; } else { // a != 0の時に実行される処理 b *= 2; } |
if else if …と複数のif文を繋げた書き方
if else
文はelse
の後に他のif文をつなげることで処理を3つ以上に分岐することができます。
if (<条件式1>) {} else if (<条件式2>) {} ...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
int a = 0; int b = 0; if (a == 0) { // <- 条件式1 // a == 0の時に実行される処理 b = 100; } else if(a == 1) { // <- 条件式2 // a == 1の時に実行される処理 b = 200; } else if(a == 2) { // <- 条件式3 // a == 2の時に実行される処理 b = 300; } else { // どの条件式にも当てはまらない時に実行される処理 b = -1; } |
注意点として、これと似たようにif文単体の後すぐにif文を書くことができますが、その場合は異なる分岐だとみなされますので注意してください。(単純に改行されていないとみなされます。)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
int a = 0; // 一応このように書くことができるが、別々の分岐処理とみなされる。 if(a == 0) { // ... } if(a == 1) { // ... } //上のコードは次のものと同じ if(a == 0) { // ... } if(a == 1) { // ... } |
ネスト(Nest、入れ子)したif文の書き方
アプリ作成中に分岐した処理の中でさらに分岐したいことが出てくるかもしれません。
そのような場合はif文で分岐した処理の中にさらにif文を書くことで対応できます。
このような入れ子構造になったものをネスト(Nest)と呼んでいます。
1 2 3 4 5 6 7 8 9 10 11 12 13 |
int a = 0; int b = 0; int c = 0; if(a == 0) { //他のif文の中にもif文を書くことができる。 // この場合は、if(a == 0 && b == 0)と書いた時と似た意味合いになるが、 // ネストした場合はaの判定をした後に追加で処理を書くことができるのが異なる。 if(b == 0) { c = 2; } else { c = -2; } } |
? 演算子
条件式を用いてある変数に代入したい値を切り替えたい場合があります。
if
文を使用してもいいですが、?
演算子を使用するともっと簡単に書くことができます。
<条件式> ? <trueの時の値> : <falseの時の値>
このように書くと条件式によって?
より後に書いた2つの値のどちらを使うか切り替えることができます。
?
演算子は変数に値を代入する用途で使われることが多いですが、それ以外にもメソッドの戻り値を返す時などにも使用することができます。
また、?
演算子も入れ子にすることができますので、2つ以上の条件式を組み合わせることができます。ですが、そのようなコードは読みづらくなりやすいのであまり書かないようにしましょう。
また、?演算子
を使用する際は必ずtrueとfalseそれぞれ書いた値の型を一致させて下さい(※)。
(※型変換が可能な型なら問題ありません。)
1 2 3 4 5 6 7 8 |
int a = 0; //?演算子 int b = a > 0 ? 100 : -100; //入れ子になった?演算子 int c = a > 0 ? 100 : b > 0 ? 200 : -200; |
switch文とは
switch
文はif
文を拡張したような制御文です。条件式に与えた値に応じて処理を分岐することができます。
分岐先の処理はcase
文の中に書いていきます。
switch(<条件式>) { ... case <値1>: <処理1> break; ... }
また、同じ処理を実行したいcase
文がある時は、続けて書くことで実行する処理をまとめることができます。
switch(<条件式>) { ... case <値1>: case <値2>: <処理1> break; ... }
どのcase文に当てはまらない場合に処理を実行したい時はdefault
文を書いて下さい。
switch(<条件式>) { ... default: <処理> break; ... }
なお処理を書いたcase
文の末尾には必ず、break
キーワードをつけて下さい。つけ忘れると、C#コンパイラーはbreak
キーワードをつけ忘れという意味合いのコンパイルエラーを出します。
また、case
文とdefault
文の並び順は自由になります。なので、先にdefault
文を書いてもOKです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
int a = 0; int b; //switch文の書き方 switch(a) { case 0: b = 1; break; case 1: b = 100; break; default: b = -1; break; } //if文で書くと次のようなものになる if(a == 0) { b = 1; } else if(a == 1) { b = 100; } else { b = -1; } |
switch
文の中には最新のC#では使用できるがUnityでは使用できないものもありますので注意して下さい。
- Type pattern
- case when句
などなど。ちょっと応用的な文法なので初心者さんは気にしなくてOKです。
switch制御文の中で変数を宣言・初期化する時の注意点
switch
文の中で変数を宣言・初期化する際にはいくつかの注意点があります。
- 変数を宣言・初期化する時は必ず
case
文の鍵括弧({})の中で行う。 - 同じ
switch
文全体には同じ名前の変数は一つだけになるようにする。 - ある
case
文で宣言・初期化した変数の型は他のcase
文でも同じ型として扱う。
別々のcase
文で同じ名前の変数を宣言・初期化する際には一番上に書いたcase
文の中で宣言・初期化を行い、それより下にあるcase
文では宣言を省略してそのまま使用することができます。
これはswitch
文のもつスコープがその中にあるcase
文で共通しているためです。
(※スコープにつきましては他の記事でご紹介します。)
【Unityで実践】 変数の状態によって制御文を使って処理を切り替える方法
今回の記事で条件分岐について紹介しました。早速、条件分岐のよくある使い方の値の検証を行ってみましょう!
Inspectorからの入力をチェックしてみよう。MonoBehaviour.OnValidate()について
MonoBehaviour
内にvoid Validate()
メソッドを定義しますと、Inspector上からSampleコンポーネントの値を変更するたびに上に書いたOnValidate
メソッドが実行されます。
これはUnityEngine.MonoBehaviour
が持つ機能の一つで、引数を持たず、void
な戻り値を持つOnValidate
と名付けられたメソッドがある時はInspecotorから値を変更した時にUnityが自動的にそのメソッドを呼び出すようになっています。
現状ではEditor拡張にその役目が置き換わっていますが、手軽にInspector上で入力した値を検証することができますので簡単に紹介します。
OnValidate()
が呼び出されるタイミングは以下のものになります。
- Inspector上から値が変更された時
- スクリプトが有効化された時
- 他のスクリプトをビルドした時
それでは実際に条件分岐を使ってみましょう!
Unityでのif文の使い方
まず初めにValueの値を変更するのに合わせてColorの色も変更するコードを書いてみましょう!
使用する条件文はif
文になります。サンプルコードではValueが1になった時、Colorを白色に変更しています。
またまだ説明していないものが含まれていますが、Meshに値が設定されている時にはその色をColorになるよう設定しています。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
using UnityEngine; public class Sample : MonoBehaviour { public int Value; public Color Color; public MeshRenderer Mesh void OnValidate() { if(Value == 1) {// Valueが1の時Colorを白色に設定する Color = Color.white; } if(Mesh != null) { Mesh.sharedMaterial.color = Color; } } } |
Unityでのif else文の使い方
Valueの値が1になった時だけしか変更しないのは物足りませんので、if else
文を使用しValueが他の値になった時にも色を変更するようにしてみましょう!
サンプルコードではネストしたif else
文を使用してValueの値が1から4になった時はColorをそれぞれ対応する色に変更し、Valueの値がそれ以外のものになったらColorを黒色にしています。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
using UnityEngine; public class Sample : MonoBehaviour { public int Value; public Color Color; void OnValidate() { if(Value == 1) { Color = Color.white; } else if(Value == 2) { Color = Color.blue; } else if(Value == 3) { Color = Color.red; } else if(Value == 4) { Color = Color.green; } else { Color = Color.black; } if(Mesh != null) { Mesh.sharedMaterial.color = Color; } } } |
Unityでのswitch文の使い方
ネストしたif
文を使用すると条件式がたくさん書く必要があり、読みづらくなりがちです。
先のサンプルコードではValue単体の値を見て処理を分岐していますので、そのような場合はswitch
文に置き換えることができます。
次のサンプルコードの動作は上のif else
文で書いたものと同じになります。ですが、switch
文を使った方が意味を把握しやすくなっています。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
using UnityEngine; public class Sample : MonoBehaviour { public int Value; public Color Color; void OnValidate() { switch(Value) { case 1: Color = Color.white; break; case 2: Color = Color.blue; break; case 3: Color = Color.red; break; case 4: Color = Color.green; break; default: Color = Color.black; break; } if(Mesh != null) { Mesh.sharedMaterial.color = Color; } } } |
ネストしたif
文とswitch
文は似たような意味合いを持つプログラムになりがちですが、一般的に一つの値がとるものに対して処理を分岐させたい時はswitch文を使用し、if else
文はそれ以外の複雑な分岐に使用するようにしましょう!
まとめ
今回の記事では制御文の一つである条件分岐について見てきました。条件分岐にはif
文とif else
文、switch
文があり、それら全てプログラムの処理を分岐するためのC#の機能になります。
この記事を簡単にまとめますと以下のようになります。
- 条件分岐を使うと変数の状態に合わせてアプリの処理を切り替えることができる。
if
文は最も基本的な条件分岐で、変数の値に応じて処理を実行したりしなかったりできる。if else
文は処理を2つに分岐させることができ、それ以上にif
文を続けることができる。?演算子
を使用すると条件式によって簡単に値を切り替えることができる。switch
文は一つの値に対するif文を簡単にした条件分岐。switch
文の各ケース分けの末尾にはbreak
キーワードをつける必要がある。
それでは、次の記事に行ってみましょう。
余談:goto文について
歴史的経緯からC#の条件分岐にはgoto
文という制御構文があります。
こちらはソースコード上にラベルをつけた部分に処理をジャンプさせることができる機能になりますが、決して安易に使用しないでください。
一見便利に見えますが、goto文を使用したコードはスパゲティコード(※)という乱雑で読みづらく修正作業がしづらい酷いコードになりやすいです。そのようなコードは悪いコードとみなされます。
goto
文自体は次の処理を好きな箇所にジャンプさせる単純な処理なのですが、人がプログラミングする上で自由度が高すぎたようです。
(※スパゲティコードはgoto文を使用しなくても処理の流れが把握しづらいコード全般を指します。)
内部的な処理から見るとgoto文は他の制御構文の裏側で使用されています、さらにコンピュータから見ると最も基本的な制御構文ではあります。
ですが、人がプログラミングする上では自由度が高すぎることはミスにも繋がりやすいため、プログラミングの世界ではif
文やswitch
文など機能に制約をつけ、人が理解しやすく、ミスしづらい方向へと進歩していっています。
goto
文は一部の場面では便利な面もあるのですが、基本的にそれを使用するようなソースコードは設計ミスだと判断してもいいでしょう。
コメント