//tips
Unityベースで作成することに限界を感じ始めたので、C#言語と全体構成に一旦立ち返る。
C#の理解を深めると同時に、応用情報技術者試験10月の範囲をカバーしていく。
応用情報技術者試験の内容は今までのC#,js,phpの内容を詳細な文章ベースで記述されているもののようなのでちょうど深堀するのに良さそう。
//C#理解
先のスクリプトの中にC#の応用的な機能が多々出てきたので、それらの確認を行なっていく。
まずはデリゲート。かなりわかりやすい説明を見つけたので記載。
デリゲートはメソッドを格納でき、デリゲート型の代表者さえ分かっていれば、格納されているメソッドを呼び出すことができる。
delegate 戻り値の型 デリゲート型名(パラメータリスト);
格納されるメソッドは、同じ戻り値型とパラメータリストを持つ。
まずこの代表者を定義し、次に実際に呼ばれるメソッドを設定していくことになる。
delegate void SampleDel(int x);
class MainClass
{
static void TestMethod(int n)
{
Console.WriteLine(n);
}
public static void Main()
{
SampleDel delvar;
delvar = new SampleDel(TestMethod);
delvar(123);//123
}
}
このように代表者のデリゲートをnewで実体化して変数にし、その引数に大元のdelegateと同じ戻り値とパラメータを持つメソッドを引数に取ることができる。
さらにdelvar = new SampleDel(TestMethod);の部分は短縮形にすることができ、
SampleDel delvar=TestMethod;
として表すことが可能。
またデリゲート型をパラメータとして使用することができ、
デリゲート型変数をパラメータとしたメソッドを作成すると、デリゲート内に格納している複数のメソッドを単一メソッドから呼び出すことができる。
delegate void SampleDel(int x);
class TestClass
{
public void TestMethod1(int n)
{
Console.WriteLine(n);
}
public static void TestMethod2(int n)
{
Console.WriteLine(n*2);
}
}
class MainClass
{
public static void MethodCallback(int p,SampleDel delvar)
{
delvar(p);
}
public static void Main()
{
TestClass t= new TestClass();
methodCallback(10,t.TestMethod1);
methodCallback(10,TestClass.TestMethod2);
}
}
TestClassに記載されている2つのデリゲートと同じ型のメソッドをMethodCallbackの引数として
methodCallback(10,t.TestMethod1);
methodCallback(10,TestClass.TestMethod2);
のように実行することができる。
上記のように複数のメソッドをデリゲートに格納することができ、追加削除も+-を使用して行える。
デリゲートに複数のメソッドが登録されていると、1回の呼び出しでそれらが全て実行される。
class MainClass
{
delegate int SampleDel(int x);
class TestClass
{
public int TestMethod1(int n)
{
return n*10;
}
public int void TestMethod2(int n)
{
return n*20;
}
}
public static void Main()
{
TestClass t= new TestClass();
SampleDel delvar=t.TestMethod;
delvar += t.TestMethod2;
Console.WriteLine(delvar(10)); //1,2が実行されるが表示は後から実行された方が優先される200
delvar -= t.TestMethod2;
Console.WriteLine(delvar(10));//100
}
}
return表示は最後に実行されたメソッド結果が表示されることになる。
デリゲートの中身に処理自体を組み込むことができ、
delegate int SampleDel(int x);
class MainClass
{
public static void Main()
{
SampleDel delvar=delegate(int n){Console.WriteLine(n);};
delvar(123);
}
}
SampleDel delvar=delegate(int n){Console.WriteLine(n);};の部分で他のメソッドを呼ぶ必要がないのでかなりシンプルになっている。
これをさらに簡略化したものがラムダ式で、このメソッドは全てラムダ式に置き換えることができる。
MyDel del= delegate(int x){return x+1;};
ラムダ式に置き換えると、
MyDel del= x => x+1;
となる。x部分がベースとなるデリゲートの引数で、その引数に対する処理が=>の後に書かれる。
もし引数部分にブロック処理を加えたい場合は、
MyDel del = a =>
{
Console.WriteLine(“aaa”);
return 0;
};
Action<int>という、一つのパラメータを受け取り、戻り値を返さない、.NETで定義されている汎用的なデリゲートを使用してみる。
Action<int>を使用することでdelegate int SampleDel(int x);を定義する手間を省くことができる。パラメータが一つで戻り値を返さない場合に使える。
C#とは、マイクロソフトによって開発されたプログラミング言語の一種で .NET Framework上で使うことを想定して設計されている。
using System;
Class MainClass
{
public static void Main()
{
Action<int> delvar=n=>{Console.WriteLine(n);};
delvar(123);
}
}
また、ラムダ式の外にあるメソッド内のローカル変数を式の中で使うことができる。
public static void Main()
{
Int b=2;
Action<int> delvar=n=>{Console.WriteLine(n*b);};
delvar(5);
}
}
また、getなどの処理もラムダ式で代用でき、
class Product {
public double Price { get; set; }
public double IncludeTaxPrice => Price * 1.08;
}
public double IncludeTaxPrice { get { return Price * 1.08; } }部分を短縮して記述することを可能にする。
public class Person
{
public string FirstName { get; set; }
public string LastName { get; set; }
public string GetFullName => FirstName + "" + LastName;
}
これも下のget部分を省いて表現している。
public class Person
{
public string FirstName { get; set; }
public string LastName { get; set; }
public string GetFullName
{
get
{
return FirstName + "" + LastName;
}
}
}
メソッドの記述も短縮でき、
public void PlayBGM()
{
_attachBGMSource.Play();
}
から
public void PlayBGM() => _attachBGMSource.Play();
のようにできる。
get=>birthday;と書かれている場合は、
get
{
Return birthday;
}
の短縮形となる。
次によく見かけるthrow式についても確認しておく。
Throwを使用できる条件は限定されており、
・ラムダ式の->の後
Static public int Throw1()=>throw new Exception(“Lambda”);
・null合体演算子??の後
object sample=null;
Var s= sample as string ?? throw new Exception();
//??はnull合体演算子と呼ばれ、nullかどうかチェックしたいときに使われる。
左側が null 値でない場合には左側を返し、null 値である場合には右側を返す。
・条件演算子の第2または3引数
static public string Throw2(int ct)
{
return (ct<0) ? throw new InvalidOperationException(“nothing”) : ct.Tostring();
//三角演算子の?でtrueならthrow,falseなら:以下の処理
}
となる。
基本的にエラーの場合に用いられる。
デリゲートが一番多く使用されるのはプログラムが直接コントロールしていないイベントアクションを扱う時で、ボタンクリックなどが該当する。
ユーザーの介在によりアクションが発生した場合に、そのイベントに対応する事前に登録しておいたイベントハンドラーを呼び出すことになる。
イベントを宣言する際には、eventをつけデリゲートを宣言する。
event デリゲート型名 イベント名;
イベントを用いたサンプルコードを見ていく。
delegate void SampleEventHandler();
Class TestClass
{
Public event SampleEventHandler ThreeEvent = delegate{};
//匿名メソッドを使ってeventを初期化
//ラムダ式だと右のようになるpublic event SampleEventHandler ThreeEvent=()=>{};
Public void OnThreeEvent()
{
for(int I=1;i=20;i++)
{
Console.WriteLine(i);
if(i%3==0)
ThreeEvent();
//3の倍数の時はイベントを発生させている
}
}
}
Class MainClass
{
public static void Main()
{
TestClass t=new TestClass();
//イベントハンドラーの追加
t.ThreeEvent +=delegate{Console.WriteLine(“XX”);};
//ラムダ式版t.ThreeEvent +=()=>Console.WriteLine(“XX”);
//イベント発生
t.OnThreeEvent();
}
}
ThreeEventは初期化によって何も入っていない状態だったので、t.ThreeEvent +=によって新たなメソッドを追加している。同じvoid型なので問題なく組みこむことができる。
そして最後にt.OnThreeEvent();を実行し、イベント発生時にThreeEventに登録された内容を実行している。