MochiuWiki : SUSE, EC, PCB
案内
メインページ
最近の更新
おまかせ表示
MediaWiki についてのヘルプ
ツール
リンク元
関連ページの更新状況
特別ページ
ページ情報
We ask for
Donations
検索
個人用ツール
ログイン
Toggle dark mode
名前空間
ページ
議論
表示
閲覧
ソースを閲覧
履歴を表示
C Sharpの基礎 - 可変長引数のソースを表示
提供: MochiuWiki : SUSE, EC, PCB
←
C Sharpの基礎 - 可変長引数
あなたには「このページの編集」を行う権限がありません。理由は以下の通りです:
この操作は、次のグループのいずれかに属する利用者のみが実行できます:
管理者
、new-group。
このページのソースの閲覧やコピーができます。
== 概要 == C#では、<code>params</code>キーワードを使用することで、メソッドの引数の数を可変にすることができる。<br> <br> <syntaxhighlight lang="c#"> // 定義側の例 int Sum(params int[] args) { // 処理 } // 利用側の例 Sum(1, 2, 3, 4, 5); // Sum(new int[] { 1, 2, 3, 4, 5 }); と同じ意味 </syntaxhighlight> <br><br> == paramsキーワード == 以下の2つの例は、可変個の整数のうち最大の整数を求めるメソッドである。<br> <br> ==== 可変長引数を使用しない場合 ==== 可変長引数を使用せずにメソッドを実装すると、以下のようになる。<br> <br> 以下の方法では、値を配列に格納してからMaxメソッドを呼び出すという操作が必要になる。<br> Maxメソッドを呼び出すたびに一時的に配列を作成して、値を格納するという作業を行うのは面倒である。<br> <syntaxhighlight lang="c#"> using System; class ParamsTest { static void Main() { int a = 314, b = 159, c = 265, d = 358, e = 979; int[] tmp = new int[]{a, b, c, d, e}; int max = Max(tmp); Console.Write("{0}\n", max); } static int Max(int[] a) { int max = a[0]; for(int i=1; i<a.Length; ++i) { if(max < a[i]) { max = a[i]; } } return max; } } </syntaxhighlight> <br> ==== 可変長引数を使用する場合 ==== C#では、<code>params</code>キーワードを使用して、可変個の引数を取るメソッドを定義することができる。<br> <br> 以下の例では、上記の例をparamsキーワードを使用して書き直している。<br> <syntaxhighlight lang="c#"> using System; class ParamsTest { static void Main() { int a = 314, b = 159, c = 265, d = 358, e = 979; int max = Max(a, b, c, d, e); // 自動的に配列を作成して値を格納する Console.Write("{0}\n", max); } static int Max(params int[] a) { int max = a[0]; for(int i=1; i<a.Length; ++i) { if(max < a[i]) { max = a[i]; } } return max; } } </syntaxhighlight> <br> メソッド定義側の変更点は、Maxメソッドの引数である<code>int[] a</code>の前に<code>params</code>キーワードを記述しただけである。<br> 呼び出し側では、手動で配列を用意して値を格納しなくとも、可変個の引数を与えてメソッドを呼び出すことができる。<br> <br><br> == サンプルコード == <code>Console.Writeメソッド</code>は、可変長引数の機構を使用している。<br> <br> 以下の例では、paramsキーワードを使用して、Console.Writeメソッドのようなものを作成している。<br> <syntaxhighlight lang="c#"> using System; class TestParams { static void Main(string[] args) { double x = 3.14; int n = 99; string s = "test string"; bool b = true; Write("x = {0}, n = {1}, s = {2}, b = {3}\n", x, n, s, b); } /// <summary> /// Console.Writeのようなもの /// {0:d5} のような書式指定はできない /// </summary> /// <param name="format">書式指定文字列</param> /// <param name="args">format を使用して書き込むオブジェクトの配列</param> static void Write(string format, params object[] args) { for(int i = 0; i < args.Length; i++) { format = format.Replace("{" + i.ToString() + "}", args[i].ToString()); } Console.Write(format); } } // 出力 // x = 3.14, n = 99, s = test string, b = True </syntaxhighlight> <br><br> == params IEnumerable == 現行のC#では、paramsキーワードを使用できるものは配列だけである。<br> <br> IEnuemrable<T>インターフェイス(System.Collections.Generic名前空間)を使用した可変長引数を記述したいという要望は多いが、<br> 現在まで実装に至っていない。<br> <br> これは、具体的にどのような型を作成して渡すことがよいかで揉めている。<br> 配列の場合は配列が具象型であるため、配列以外を作成する選択肢は無いが、IEnumerable<T>の場合は型の種類が選択できる。<br> 現在、配列よりも都合がよい型を採用できないか(値型にしてヒープ確保を避ける、immutableな型にして安全性を上げる等)が検討されている。<br> <syntaxhighlight lang="c#"> // コンパイル可能 static int Sum(params int[] source) { var sum = 0; foreach (var x in source) { sum += x; } return sum; } // コンパイルエラー static int Sum(params IEnumerable<int> source) { var sum = 0; foreach (var x in source) { sum += x; return sum; } } </syntaxhighlight> <br><br> == 可変長引数を引数無しで呼ぶ == 可変長引数があるメソッドは、引数無しで呼ぶこともできる。<br> この場合、呼び出されたメソッドには、空配列(長さ0の配列)が渡される。<br> <syntaxhighlight lang="c#"> using System; class Program { static void Main(string[] args) { var x = Sum(); Console.WriteLine(x); // 0 } static int Sum(params int[] source) { // 引数無しで呼ばれた場合、配列sourceには空配列が代入される(配列sourceは、nullではないことに注意すること) var sum = 0; foreach (var x in source) { sum += x; } return sum; } } </syntaxhighlight> <br> 上記において、空配列の生成方法は、.NET Frameworkのバージョンによって変わる。<br> .NET Framework 4.6以降 / .NET Coreでは、<code>Array.Empty</code>という空配列を作成するためのメソッドがあるため、このメソッドが呼ばれる。<br> .NET Framework 4.5以前では、<code>new T[0]</code>で空配列が生成される。<br> <br> つまり、上記のサンプルコードにおいて、<code>var x = Sum()</code>は、.NET Framework 4.5以前であれば、以下のように解釈される。<br> <syntaxhighlight lang="c#"> // .NET Framework 4.5以前 var x = Sum(new int[0]); // .NET Framework 4.6以降 var x = Sum(Array.Empty<int>()); </syntaxhighlight> <br> 2つの方法が存在する理由は、Array.Emptyメソッドを使用する方がパフォーマンスが良いからである。<br> new int[0]の場合、メソッドの呼び出しのために配列のインスタンスが生成されるが、<br> Array.Emptyメソッドの場合、最初に生成した1つのインスタンスをキャッシュして使いまわす。<br> <br> これは、破壊的変更なので注意すること。<br> <br> 例えば、以下のサンプルコードの挙動は.NET Frameworkのバージョンによって変わる。<br> <syntaxhighlight lang="c#"> using System; class Program { static void Main(string[] args) { var x = IsCached(); Console.WriteLine(x); var y = IsCached(); Console.WriteLine(y); // ターゲットによって結果が変わる } static int[] prev; static bool IsCached(params int[] source) { // .NET Framework 4.5以前の場合、毎回違う配列をnewして渡す // .NET Framework 4.6以降の場合、毎回同じインスタンスを使いまわす if (prev == source) { return true; } prev = source; return false; } } </syntaxhighlight> <br><br> __FORCETOC__ [[カテゴリ:C_Sharp]]
C Sharpの基礎 - 可変長引数
に戻る。
案内
メインページ
最近の更新
おまかせ表示
MediaWiki についてのヘルプ
ツール
リンク元
関連ページの更新状況
特別ページ
ページ情報
We ask for
Donations
Collapse