講義メモ ・p.195「メソッドのオーバーロード」から 提出:ミニ演習 mini193.cs・改 ・アレンジ演習:p.191 changearray01.csを元に、引数のaとbの和をout waで、差をout saで、積をout seiで返すメソッドにしてみよう  void modify(int a, int b, out int wa, out int sa, out int seki){…} 作成例 //ミニ演習 mini193.cs・改 using System; class change { public void modify(int a, int b, out int wa, out int sa, out int seki) { //aとbの和差積を返すメソッド wa = a + b; //和を格納する sa = (a > b) ? a - b : b - a; //差を格納する seki = a * b; //積を格納する } } class changearray01 { public static void Main(){ change c = new change(); int x, y, z; //宣言のみで良い c.modify(10, 20, out x, out y, out z); //参照渡しで和差積を書きこんでもらう Console.WriteLine("{0}と{1}の和は{2},差は{3},積は{4}", 10, 20, x, y, z); } } p.195 メソッドのオーバーロード ・p.168のとおり、シグニチャ(引数の数、型、並び)が異なるコンストラクタを複数定義できることをオーバーロードという ・メソッドもオーバーロードが可能で、シグニチャが異なる同じ名前のメソッドを複数定義できる ・なお、メソッドのシグニチャには戻り値型は含まれないので、戻り値型のみが異なるメソッドの複数定義はできない ・これは呼び出し時に区別できないから ・なお、整数⇒実数のように暗黙の型変換により一致するオーバーロードがあれば、それが採用される ・メソッドのオーバーロードにより、同じ意味のメソッドは同じ名前にできる アレンジ演習:p.195 overload01.cs ・第5のバージョンとして「Method(double x, double y)」を適当な内容で追加し、呼び出せることを確認しよう ・Mainメソッドで、m.Method(5.1, 6)を呼び出すと、暗黙の型変換によりこの第5のバージョンが動作することを確認しよう 作成例 //p.195 overload01.cs using System; class manymethods { public int Method(int x) { Console.WriteLine("第1のバージョンが呼ばれました"); return x + 10; } public double Method(double x) { Console.WriteLine("第2のバージョンが呼ばれました"); return x * 2; } public string Method(string x) { Console.WriteLine("第3のバージョンが呼ばれました"); return x += "です"; } public int Method(int x, int y) { Console.WriteLine("第4のバージョンか呼ばれました"); return x + y; } public double Method(double x, double y) { //【以下追加】 Console.WriteLine("第5のバージョンか呼ばれました"); return x + y; } } class overload01 { public static void Main() { manymethods m = new manymethods(); Console.WriteLine("その戻り値は「{0}」です", m.Method(3)); //第1のバージョンを呼ぶ Console.WriteLine("その戻り値は「{0}」です", m.Method(3.2)); //第2のバージョンを呼ぶ Console.WriteLine("その戻り値は「{0}」です", m.Method("粂井")); //第3のバージョンを呼ぶ Console.WriteLine("その戻り値は「{0}」です", m.Method(5, 6)); //第4のバージョンを呼ぶ Console.WriteLine("その戻り値は「{0}」です", m.Method(5.1, 6)); //【追加】第5のバージョンを呼ぶ } } p.197 Mainメソッドのオーバーロード ・Mainメソッドは特殊なメソッドであり、コンソールプログラム等の動作の始点になる ・通常、public static voidとし、引数は指定しないが、バリエーション(オーバーロード)がある。 ・戻り値型をvoidからintにすると「return 整数値」が記述可能になり、このプログラムを呼び出した元に整数値を返すことができる ・なお、VisualStudioのデバッグ機能から呼び出した場合は、返される値は表示されないが、一般に、正常終了したら0を、でなければ0以外を返すことが多い ・Windowsではビルド済のプログラムをVisualStudioを介さずに実行し、戻り値を表示する方法がある(後述) ・また、引数にstring[]=文字列配列を指定すると、起動時に、システムから複数の文字列を渡すことができる ・この文字列をコマンドライン引数という ・VisualStudioでは、デバッグのプロパティでコマンドライン引数を指定できる ・Windowsではビルド済のプログラムをVisualStudioを介さずに実行し、実行時にコマンドライン引数を指定する方法がある(後述) p.198 main01.cs:VisualStudioにおける実行方法 ① ソースを記述する ②「デバッグ」「●のデバッグプロパティ」 ③「コマンドライン引数」に「cat dog apple」と入力 ④「ファイル」「すべて保存」 ⑤「デバッグなしで開始」 p.198 main01.cs //p.198 main01.cs using System; class main01 { public static int Main(string[] s) { //コマンドライン引数を受け取るMainメソッド int n; n = s.Length; //引数の数=配列の要素数を得る Console.WriteLine("引数の個数は{0}個です", n); if (n != 0) { //引数があれば(※このif文は実際は無用) for (int i = 0; i < n; i++) { //コマンドライン引数全てについて繰返す Console.WriteLine("引数{0} : {1}", i + 1, s[i]); } } return 0; //正常終了を返す } } p.198 main01.cs:開発者用コマンドプロンプトにおける実行方法 ① ソースを記述し「ビルド」「ソリューションのビルド」(※既に実行済なら不用) ②「ツール」「コマンドライン」「開発者用コマンドプロンプト」 ③「プロジェクト名\bin\debug\プロジェクト名 コマンドライン引数」を入力し、Enterで実行 例:Project1\bin\debug\Project1 cat dog apple ※ この時、②で表示される文字列をカレントディレクトリ(パス)という 例:F:\ha242_AkibaC#\Project1 p.198 main01.cs:通常のコマンドプロンプトにおける実行方法 ① Windows10では「スタート」「Windowsシステムツール」「コマンドプロンプト」   Windows11では「スタート」「すべてのアプリ」「Windowsツール」「コマンドプロンプト」 ② カレントディレクトリ(パス)の先頭文字(ドライブレター)が「C」でなければ、ドライブレターと「:」を入力し、Enter 例:F: ③ カレントディレクトリ(パス)と「\」を入力し、続けて「プロジェクト名\bin\debug\プロジェクト名 コマンドライン引数」を入力し、Enterで実行 例:F:\ha242_AkibaC#\Project1\Project1\bin\debug\Project1 cat dog apple p.199 main02.cs:通常のコマンドプロンプトで実行し戻り値を表示する方法 ① Visual Studioでmain02.csのソースを記述し「ビルド」「ソリューションのビルド」 ② Windows10では「スタート」「Windowsシステムツール」「コマンドプロンプト」   Windows11では「スタート」「すべてのアプリ」「Windowsツール」「コマンドプロンプト」 ③ カレントディレクトリ(パス)の先頭文字(ドライブレター)が「C」でなければ、ドライブレターと「:」を入力し、Enter 例:F: ④ カレントディレクトリ(パス)と「\」を入力し、続けて「プロジェクト名\bin\debug\プロジェクト名 コマンドライン引数」を入力し、Enterで実行 例:F:\ha242_AkibaC#\Project1\Project1\bin\debug\Project1 cat dog apple ⑤「echo %errorlevel%」と入力しEnterを押すと、戻り値が表示される p.199 main02.cs //p.199 main02.cs using System; class main02 { public static int Main(string[] args) { //コマンドライン引数を受け取り戻り値を返す if (args.Length != 1) { //コマンドライン引数が1個ではない? return -1; //-1を返す } else { //コマンドライン引数が1個? if (!Char.IsDigit(args[0][0])) { //第0要素の0文字目(引数の先頭文字)が数字以外? return -2; //-2を返す } } return int.Parse(args[0]); //第0要素を整数化して返す } } 通常のコマンドプロンプトで実行し戻り値を表示する方法の例 F:\>F:\ha242_AkibaC#\Project1\Project1\bin\debug\Project1 F:\>echo %errorlevel% -1 F:\>F:\ha242_AkibaC#\Project1\Project1\bin\debug\Project1 cat dog F:\>echo %errorlevel% -1 F:\>F:\ha242_AkibaC#\Project1\Project1\bin\debug\Project1 cat F:\>echo %errorlevel% -2 F:\>F:\ha242_AkibaC#\Project1\Project1\bin\debug\Project1 2100000000 F:\>echo %errorlevel% 2100000000 ※ p.200のバッチファイルの説明は割愛します p.201 引数が可変個のメソッド ・メソッドの引数にparamsキーワードと配列を指定することで、引数が可変個のメソッドになる ・よって、同型の引数をいくつでも指定できる1メソッドが記述できる ・書式: アクセス修飾子 戻り値型 メソッド名(params 配列型[] 仮引数) {…} ・メソッド内部では仮引数を配列として、各引数はその要素になる ・よって、引数の数は、仮引数.Lengthで得ると良い ・引数が0個でもかまわないが、要素数0の配列になるので、要素を使用すると異常終了する アレンジ演習:p.201 params01.cs ・「if(animal1.Length == 0)」は不用なので消そう ・その後ろのfor文はforeachで書き換えよう ・Mainにおいて、引数が1個の場合、2個の場合を加えよう ・また、引数をint型にしたメソッドでオーバーロードできるが条件があることを確認しよう  ⇒ 引数が0個である呼び出しをすると、両方にマッチしてしまうので、エラーになる 作成例 //p.201 params01.cs using System; class MyClass { public void show(params string[] animal) { //string型の可変個引数のメソッド foreach (var w in animal) { //全引数について繰返す Console.WriteLine("{0}さんがいます", w); } } public void show(params int[] animal) { //int型の可変個引数のメソッド foreach (var w in animal) { //全引数について繰返す Console.WriteLine("{0}です", w); } } } class params01 { public static void Main() { MyClass mc = new MyClass(); //mc.show(); //showメソッドをオーバーロードにしたので区別不可でエラーになる mc.show("ぱんだ"); mc.show("いぬ", "ねこ"); mc.show("きりん", "ぞう", "かば"); mc.show(100); mc.show(200, 300); } } ミニ演習:mini202.cs ・実数の可変個引数を受け取って、平均値を返す double ave(params double[]) を作成し、動作を確認しよう 作成例 //ミニ演習:mini202.cs using System; class MyClass { public double ave(params double[] val) { //double型の可変個引数のメソッド double sum = 0.0; //合計 foreach (var w in val) { //全引数について繰返す sum += w; //合計に足し込む } return sum / val.Length; //平均値を返す } } class params01 { public static void Main() { MyClass mc = new MyClass(); Console.WriteLine(" = {0}", mc.ave()); Console.WriteLine("1.1 = {0}", mc.ave(1.1)); Console.WriteLine("1.1, 2.2 = {0}", mc.ave(1.1, 2.2)); Console.WriteLine("1.1, 2.2, 3.3 = {0}", mc.ave(1.1, 2.2, 3.3)); } } p.202 静的メンバ ・通常、クラスの各メンバはインスタンスに所属する  例:Slimeクラスにhpを定義すると、Slimeクラスのインスタンスslalinに所属し、slalin.hpになる ・しかし、インスタンスに所属する必要がないような=クラスに所属するメンバも記述できる ・それが静的メンバで、staticを前置して示す  例:Slimeクラスに「生成したスライム数」を持たせる場合、インスタンスには所属しないので、クラスで持つ方が良い ・また、インスタンス変数を全く用いないメソッドもクラスで持つ方が良く、これを静的メソッドという ・静的メンバはクラスに所属するので「クラス名.」を前に付けて実行する ・よって、静的メンバはインスタンスの生成をしなくても利用できる ・なお、Console.WriteLineは、Consoleクラスの静的メソッドなので「Console.」を前につけている ・また、Mathクラスのメンバの大半は静的メンバ(例:Math.PI) ・近い理由で、Mainメソッドも静的メソッドである必要があるので「static」を前置する ・逆に言えば、静的メンバはインスタンスごとにはならない特殊なものであり、オブジェクト指向のメリットを生かせないので乱用は避けること。 ※ つまり、設計図に直接データを書き込んでいるようなイメージ アレンジ演習:p.203 static01.cs ・変数xにMyClassのインスタンスの生成数を格納するようにして、動作を確認しよう ・生成はデフォルトコンストラクタでのみ行うとする 作成例 //p.203 static01.cs using System; class MyClass { public static int x; //静的データメンバ(インスタンス数) public static void showX() { //静的メソッド Console.WriteLine("x = {0}", x); } public MyClass() { //【追加】コンストラクタ x++; //静的データメンバをインクリメント } } class static01 { public static void Main() { MyClass.x = 0; //静的データメンバなので直接アクセスできる MyClass.showX(); //静的メソッドなので直接呼び出せる MyClass m1 = new MyClass(); //【追加】コンストラクタが呼ばれる MyClass.showX(); //静的メソッドなので直接呼び出せる } } 作成例(発展形) //p.203 static01.cs using System; class MyClass { public static int x; //静的データメンバ(インスタンス数) public static void showX() { //静的メソッド Console.WriteLine("x = {0}", x); } public int n; //【追加】自分は何番目かを示すインスタンス変数 public MyClass() { //【追加】コンストラクタ x++; //静的データメンバをインクリメント n = x; //自分は何番目か } public void showN() { //【追加】インスタンスメソッド Console.WriteLine("ボクは{0}番目です", n); } } class static01 { public static void Main() { MyClass.x = 0; //静的データメンバなので直接アクセスできる MyClass.showX(); //静的メソッドなので直接呼び出せる MyClass m1 = new MyClass(); //コンストラクタが呼ばれる m1.showN(); //【追加】インスタンスメソッドで何番目かを表示 MyClass m2 = new MyClass(); //コンストラクタが呼ばれる m2.showN(); //【追加】インスタンスメソッドで何番目かを表示 MyClass m3 = new MyClass(); //コンストラクタが呼ばれる m3.showN(); //【追加】インスタンスメソッドで何番目かを表示 } } 提出:アレンジ演習:p.203 static01.cs 次回予告:p.204「静的クラス」から