C# 配列、インデックスとして負の数の配列を持たないのはなぜですか? この状況は、非常に役立つ場合があります。特に、特別なタイプのソートにおける高速アルゴリズムの場合。2 つの質問: 1) なぜですか? 2) 効率的な回避策はありますか?
4 に答える
インデクサーを使用して、いつでも独自のクラスを実装できます。例えば:
public class MyClass {
public String this[int index] {
get {
// ...
}
set {
// ...
}
}
}
whereString
は例として戻り値の型です。
このArray.CreateInstance
メソッド は、理論的にはゼロ以外の下限を持つ配列を作成するために使用できます。
Array.CreateInstance(
elementType: typeof(T),
lengths: new int[] { length },
lowerBounds: new int[] { lowerBound });
唯一の問題は、C# では返された配列をT[]
;にキャストできないことです。これは、多次元配列 (T[,]
など) に対してのみ許可され、機能します。
これは、CLR がゼロの下限を持つ 1 次元配列を特別に扱うという事実が原因である可能性があります。これらは「ベクトル」と呼ばれ、多次元配列もゼロ以外の下限を持つものも受け取らないいくつかの特別な最適化を取得します。
しかし、実際には、なぜC# が 1 次元配列をベクトルに制限しているのか、はっきりとはわかりません。
一部の言語では、項目に対するデータ構造への基になるオフセットがゼロから始まるため、配列はゼロから始まります。これが最も単純な実装であり、最適な方法で使用するかどうかはプログラマーに任されています。
一部の言語では他のベース インデックスを使用できますが、インデックスからのオフセットを計算するための追加コストが発生します。より単純なコードで得られるものは、配列のより複雑な実装で失われます。
最も効率的な回避策は、配列にアクセスするときにインデックスを自分で調整することです。よりクリーンなコードを提供するソリューションは他にもありますが、それほど効率的ではありません。たとえば、配列をクラスでラップし、インデックスを調整するインデクサーを提供できます。これにより、妥当な量のオーバーヘッドでシームレスな実装が実現します。
配列をラップし、アクセス時にインデックス変換を提供する独自のクラスを作成できます。あなたはそのようなものを書きたいと思うでしょう:
public class ArrayWithAnyIndexes<ArrayType>
{
private ArrayType[] arrayToWrap;
private int firstIndex;
public ArrayWithAnyIndexes(ArrayType[] arrayToWrap, int firstIndex)
{
this.arrayToWrap = arrayToWrap;
this.firstIndex = firstIndex;
}
public ArrayTypethis[int index] {
public get {
return this.arrayToWrap[index - firstIndex];
}
public set {
this.arrayToWrap[index - firstIndex] = value;
}
}
}