メソッドの引数と「可変長」
C#でメソッドを定義する際、通常は引数の数と型を固定します(例: int Calulate(int a, int b))。
しかし、時には「引数が2個の場合も、5個の場合も、10個の場合も、すべて同じメソッドで処理したい」という要求があります。例えば、渡されたすべての数値を合計するメソッドなどです。
この要求に「メソッドのオーバーロード」で対応しようとすると、Sum(int a, int b)、Sum(int a, int b, int c)…のように、引数の数だけメソッドを定義する必要があり、非常に冗長になります。
この問題を解決するのが、C#の params キーワードです。paramsを使用すると、メソッドが「可変長引数」(引数の数が可変)を受け取れるようになります。
paramsキーワードの基本構文
paramsキーワードは、メソッドのシグネチャ(引数定義)の最後に、配列型(例: int[], string[])の引数に対して指定します。
public [戻り値の型] [メソッド名](params [型名][] [引数名])
{
// メソッドの内部では、[引数名] は通常の配列として扱われる
}
paramsの主なルール:
- メソッドの引数リストの中で、
paramsキーワードは最後に配置しなければなりません。 paramsキーワードは、1つのメソッド定義につき1回だけ使用できます。
paramsの使用例
paramsキーワードの最も一般的な使い方は、複数の数値を受け取って集計するユーティリティメソッドです。ここでは、渡されたすべてのdouble型の値の「平均値」を計算するメソッドを例にします。
ユーティリティクラスの定義
CalculateAverageメソッドは、params double[] valuesを引数に取ります。これにより、呼び出し側は数値をカンマ区切りで自由に渡すことができます。
using System;
using System.Linq; // LINQ を使用する場合
/// <summary>
/// 計算ユーティリティクラス
/// </summary>
public static class CalculationUtility
{
/// <summary>
/// 可変長引数 (double) を受け取り、その平均値を計算します。
/// </summary>
/// <param name="values">平均を計算する0個以上の double 値</param>
/// <returns>平均値。引数が0個の場合は 0.0 を返します。</returns>
public static double CalculateAverage(params double[] values)
{
// 呼び出し側が引数を0個で呼び出すことも可能
// values は null にはならないが、Length 0 の配列にはなる
if (values.Length == 0)
{
return 0.0;
}
// メソッド内部では 'values' は通常の double[] 配列として扱える
double sum = 0.0;
foreach (var value in values)
{
sum += value;
}
// LINQ を使っても同じ (using System.Linq; が必要)
// double sum = values.Sum();
return sum / values.Length;
}
}
paramsメソッドの呼び出し方
paramsで定義されたメソッドは、呼び出し側(Mainメソッドなど)から見ると、非常に柔軟な呼び出し方が可能になります。
コード例(paramsメソッドの呼び出し)
using System;
public class Program
{
public static void Main()
{
// 1. 引数をカンマ区切りで渡す
// コンパイラが (10.5, 20.0, 30.5) を new double[] { 10.5, 20.0, 30.5 } に変換
double avg1 = CalculationUtility.CalculateAverage(10.5, 20.0, 30.5);
Console.WriteLine($"3つの引数の平均: {avg1}");
// 2. 引数の数を変えてもよい
double avg2 = CalculationUtility.CalculateAverage(5.0, 10.0, 15.0, 20.0, 25.0);
Console.WriteLine($"5つの引数の平均: {avg2}");
// 3. 引数 0 個で呼び出す
double avg3 = CalculationUtility.CalculateAverage();
Console.WriteLine($"引数なしの場合: {avg3}");
// 4. 配列 (double[]) を直接渡す
// 既に配列としてデータを持っている場合も渡せる
double[] dataSet = { 100.0, 200.0 };
double avg4 = CalculationUtility.CalculateAverage(dataSet);
Console.WriteLine($"配列を渡した場合: {avg4}");
}
}
出力結果:
3つの引数の平均: 20.333333333333332
5つの引数の平均: 15
引数なしの場合: 0
配列を渡した場合: 150
paramsと他の引数の組み合わせ
paramsは「最後の引数」である必要があるため、通常の引数と組み合わせることも可能です。
/// <summary>
/// ログID (必須) と、可変長のタグ (オプション) を受け取る
/// </summary>
public void Log(int logId, params string[] tags)
{
// logId は必須の int
// tags は string[] (0個以上のタグ)
string tagsString = (tags.Length > 0)
? string.Join(", ", tags)
: "No Tags";
Console.WriteLine($"LogID: {logId} - Tags: [{tagsString}]");
}
// 呼び出し例
// Log(101, "Error", "Database");
// Log(102); // tags は 0 個の配列になる
まとめ
paramsキーワードは、メソッドの引数を可変長にするための構文(シンタックスシュガー)です。
- メソッド定義側(
params T[] args): 引数を常に配列として受け取ります。 - メソッド呼び出し側: 引数をカンマ区切りで渡すことも、配列で渡すことも、**省略(0個)**することも可能になり、APIの利便性が大幅に向上します。
