C#で複数の値の最大値・最小値を取得

Math クラスMath.Max()Math.Min()は2つの値しか比べられない。

任意の個数の複数の値から最大値、最小値を取得したい。こんな↓イメージ。

Max(0, 1, 2, 3, 4); // => 4
Min(0, 1, 2, 3, 4); // => 0

paramsで可変長引数

  • params (C# リファレンス)

    params キーワードを使用すると、可変個の引数を受け取るメソッド パラメーターを指定できます。

    パラメーター宣言で指定した型の引数のコンマ区切りのリスト、または指定した型の引数の配列を渡すことができます。 また、引数を渡さないこともできます。 引数を渡さない場合、params リストの長さはゼロになります。

引数が渡されない場合も考慮しておく必要がある。とりあえず0を返すようにしているが、ちゃんと例外処理したほうがよい。

public int Max(params int[] nums)
{
// 引数が渡されない場合
if(nums.Length == 0) return 0;
int max = nums[0];
for(int i = 1; i < nums.Length; i++)
{
max = max > nums[i] ? max : nums[i];
// Minの場合は不等号を逆にすればOK
}
return max;
}

引数として配列も渡せる。

Max(0, 1, 2, 3, 4); // => 4
int[] numbers = {0, 1, 2, 3, 4};
Max(numbers); // => 4

ジェネリック

intdoubleなどの型ごとにメソッドをつくるのは面倒なので、ジェネリックで複数の型に対応させる。

public T Max<T>(params T[] nums) where T : IComparable
{
if(nums.Length == 0) return default(T);
T max = nums[0];
for(int i = 1; i < nums.Length; i++)
{
max = max.CompareTo(nums[i]) > 0 ? max : nums[i];
// Minの場合は不等号を逆にすればOK
}
return max;
}

メソッドを呼び出すときは型引数を使用するが、省略することも出来る。省略された型引数はコンパイラが推論する。

Max<int>(0, 1, 2, 3, 4); // => 4
Max<double>(0.0, 0.1, 0.2, 0.3, 0.4); // => 0.4
Max(0, 1, 2, 3, 4); // => 4
Max(0.0, 0.1, 0.2, 0.3, 0.4); // => 0.4

whereとIComparable

今回は引数同士を比較するので、使用される型を比較が可能な型に限定する必要がある。where T : IComparableの部分で型に制約をもたせている。

IComparable型はCompareToメソッドを持っており、これを利用して値の比較を行う。

  • IComparable.CompareTo メソッド (System)

    現在のインスタンスを同じ型の別のオブジェクトと比較し、現在のインスタンスの並べ替え順序での位置が、比較対象のオブジェクトと比べて前か、後か、または同じかを示す整数を返します。

instance.CompareTo(object)の戻り値と比較結果は以下のようになる。

戻り値 比較結果
0より小さい値 instance < object
0 instance = object
0より大きい値 instance > object

default(T)

規定値を指定したい場合に用いる。

注意点

params使用時は引数0個も許されているが、同時にジェネリックも使う場合、型引数を省略して引数0個だとエラーになる。

Max<int>(); // => 0 (default(int))
Max(); // => error

CS1501のエラーが出る。

$ error CS1501: No overload for method `Max' takes `0' arguments
スポンサーリンク

関連記事