配列の引数
配列の引数として、int型に加えて、Index,Range型が追加された。
これによって、関数の引数にもIndex,Rangeが使えるようになって、使い方の幅が広がった。
しかし、int,Index,Rangeそれぞれに対して関数のオーバーロードをすると面倒臭いケアレスミスの懸念が増える。
int,Index,Rangeを全て受けられるようにしたい
旧
var ex = new Sum();
int i = ex[5];
int j = ex[^3];
int k = ex[2..5];
とできるクラスを作るときに
class Sum
{
int[] values;
public int this[int i] => values[i];
public int this[Index i] => values[i];
public int this[Range r] => values[r].Sum();
}
ではなく
class Sum
{
int[] values;
public int this[XRange r] => values[(Range)r].Sum();
}
とかけるようなXRangeクラスを作りたい。
もちろん、合計しない場合は、int,IndexとRangeで戻り値の型が違うので、あんまりメリットはない。
また、前述のように関数が1つの場合は、素直に全てオーバーロードを書いたほうが良いだろう。
それでも、同じような関数が複数あった場合に便利だと考えた。
というか必要に迫られて実装した。
新(例を見直した)
var ex = new Sum();
int i = ex[5, 3];
int j = ex[^3, ^2];
int k = ex[2..5, 3..8];
とできるクラスを作るときに
class Sum
{
int[][] cells;
public int this[Index row, Index column] => cells[row][column];
public int this[Index row, Range columns] => values[row][columns].Sum();
public int this[Range rows, Index column] => values[rows].Sum(r => r[column]);
public int this[Range rows, Range columns] => values[rows].Sum(r => r[columns].Sum());
}
ではなく
class Sum
{
int[][] cells;
public int this[XRange rows, XRange columns] => cells[rows].Sum(r => r[columns].Sum());
}
とかけるようなXRangeクラスを作りたい。
もちろん、合計しない場合は、int,IndexとRangeで戻り値の型が違うので、あんまりメリットはない。
例は、行列の2次元だが、次元が増える分だけメリットも増えると思う。
XRangeクラス
前述で使用したXRange関数の実装はこれ
public class XRange
{
public static implicit operator XRange(int i) => new(i..++i);
public static implicit operator XRange(Index i) => new(i..Next(i));
public static implicit operator XRange(Range r) => new(r);
public static implicit operator Range(XRange r) => r.value;
static Index Next(Index i) => new(i.Value + (i.IsFromEnd ? -1 : 1), i.IsFromEnd);
readonly Range value;
XRange(Range r) => value = r;
public Index Start => value.Start;
public Index End => value.End;
public (int Offset, int Length) GetOffsetAndLength(int length)
{
var left = value.Start.GetOffset(length);
var right = value.End.Value > length ? left + 1 : value.End.GetOffset(length);
return (left, right - left);
}
}
まとめ
暗黙の型変換を使って、int,Index,Rangeから変換できるようにした。
勝手に変換されてしまうので、ソースが読み難くなる気もする。
型変換を何回も挟むので、パフォーマンスも悪いと思われる。