c# インデクサーの例をたくさん見てきましたが、実際の状況でどのように役立つでしょうか。
深刻な機能でなければ、C# の第一人者がこれを追加しなかったことはわかっていますが、インデクサーを使用する現実世界の状況 (foo bar のものではない) は考えられません。
注:関連する質問が存在することは認識していますが、あまり役に立ちません。
私がインデクサーを見る方法は、(正しいか間違っているか!) インデックスによって何かにアクセスする方が、他の方法でアクセスするよりも効率的であるはずです。その方法でアクセスしたときに値をすばやく検索できるようにするインデックスの。
古典的な例は配列です。コード myarray[3] を使用して配列の要素 n にアクセスすると、コンパイラ/インタープリターは配列の (メモリに関する) 要素の大きさを認識し、配列からのオフセットとして扱うことができます。配列の開始。また"for(int i = 0; i < myarray.length; i++) { if (i = 3) then { .. do stuff } }"
、効率が低下する可能性があります (決してそうしたくないというわけではありません)。また、配列が悪い例であることも示しています。
たとえば、DVD を格納するコレクション クラスがあるとします。
public class DVDCollection
{
private Dictionary<string, DVD> store = null;
private Dictionary<ProductId, string> dvdsByProductId = null;
public DVDCollection()
{
// gets DVD data from somewhere and stores it *by* TITLE in "store"
// stores a lookup set of DVD ProductId's and names in "dvdsByProductid"
store = new Dictionary<string, DVD>();
dvdsByProductId = new Dictionary<ProductId, string>();
}
// Get the DVD concerned, using an index, by product Id
public DVD this[ProductId index]
{
var title = dvdsByProductId[index];
return store[title];
}
}
ちょうど私の 2p ですが、私が言ったように.. 私は常に「インデクサー」を何かからデータを取得する便利な方法と考えてきました。
Skurmedel が言及したように、最も明白な例はList<T>
とDictionary<TKey, TValue>
です。あなたは何よりも好きですか:
List<string> list = new List<string> { "a", "b", "c" };
string value = list[1]; // This is using an indexer
Dictionary<string, string> dictionary = new Dictionary<string, string>
{
{ "foo", "bar" },
{ "x", "y" }
};
string value = dictionary["x"]; // This is using an indexer
? インデクサーを作成する必要があるのは比較的まれかもしれませんが(通常はコレクションのようなクラスを作成する場合)、かなり頻繁に使用していると思います。
Microsoftには、インデクサーを使用してファイルをバイト配列として扱う例があります。
public byte this[long index]
{
// Read one byte at offset index and return it.
get
{
byte[] buffer = new byte[1];
stream.Seek(index, SeekOrigin.Begin);
stream.Read(buffer, 0, 1);
return buffer[0];
}
// Write one byte at offset index and return it.
set
{
byte[] buffer = new byte[1] {value};
stream.Seek(index, SeekOrigin.Begin);
stream.Write(buffer, 0, 1);
}
}
コレクションに配置された順序とは異なる順序でインデックスを作成できるようにしたいオブジェクトのコレクションがあるとします。以下の例では、オブジェクトの 'Location' プロパティを使用し、インデクサーを使用して、場所に一致するコレクション内のすべてのオブジェクトを返す方法を確認できます。2 番目の例では、特定の Count( ) オブジェクトの。
class MyCollection {
public IEnumerable<MyObject> this[string indexer] {
get{ return this.Where(p => p.Location == indexer); }
}
public IEnumerable<MyObject> this[int size] {
get{ return this.Where(p => p.Count() == size);}
}
}
.NET がジェネリックになると、私が (厳密に型指定されたコレクションを実装するために) インデクサーを実装する最大の理由はなくなりました。
コレクション型クラスの構文糖衣です。そのようなクラスを書く理由はありませんでした。それを使用するクラスはすでに実装されているため、「実生活」での使用は非常にまれだと思います。
ASP.Net では、Request、Session、または Application オブジェクトのいずれかから何かを読み取るなど、インデクサーが使用されるいくつかの異なる場合があります。何かが Session オブジェクトまたは Application オブジェクトに格納され、何度も何度も使用されるだけの場合をよく見てきました。
http://code-kings.blogspot.in/2012/09/indexers-in-c-5.html
インデクサーは、クラスが配列として動作できるようにする C# プログラム内の要素です。クラス全体を配列として使用できます。この配列には、任意のタイプの変数を格納できます。変数は別の場所に格納されますが、クラス名自体によってアドレス指定されます。整数、文字列、ブール値などのインデクサーを作成することは、実現可能なアイデアです。これらのインデクサーは、クラスのオブジェクトに対して効果的に機能します。
クラスの学生のロール番号を格納するクラス インデクサーを作成したとします。さらに、obj1 という名前のこのクラスのオブジェクトを作成したとします。obj1[0] と言うとき、ロールの最初の学生を参照しています。同様に、obj1[1] はロールの 2 番目の生徒を参照します。
したがって、オブジェクトはインデックス付きの値を使用して、クラスにプライベートまたはパブリックに格納されている整数変数を参照します。この機能を持っていなかったと仮定すると、おそらく次のように参照することになります (これは長くなります):
obj1.RollNumberVariable[0]
obj1.RollNumberVariable[1].
ここで、RollNumberVariable は、現在の生徒オブジェクトのロール番号を参照する整数変数です。
詳細についてはhttp://code-kings.blogspot.in/2012/09/indexers-in-c-5.html
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace IndexerSample
{
class FailSoftArray
{
int[] a; // reference to underlying array
public int Length; // Length is public
public bool ErrFlag; // indicates outcome of last operation
// Construct array given its size.
public FailSoftArray(int size)
{
a = new int[size];
Length = size;
}
// This is the indexer for FailSoftArray.
public int this[int index]
{
// This is the get accessor.
get
{
if (ok(index))
{
ErrFlag = false;
return a[index];
}
else
{
ErrFlag = true;
return 0;
}
}
// This is the set accessor.
set
{
if (ok(index))
{
a[index] = value;
ErrFlag = false;
}
else ErrFlag = true;
}
}
// Return true if index is within bounds.
private bool ok(int index)
{
if (index >= 0 & index < Length) return true;
return false;
}
}
class Program
{
static void Main(string[] args)
{
FailSoftArray fs = new FailSoftArray(5);
int x;
// Show quiet failures.
Console.WriteLine("Fail quietly.");
for (int i = 0; i < (fs.Length * 2); i++)
fs[i] = i * 10;
for (int i = 0; i < (fs.Length * 2); i++)
{
x = fs[i];
if (x != -1) Console.Write(x + " ");
}
Console.WriteLine();
// Now, display failures.
Console.WriteLine("\nFail with error reports.");
for (int i = 0; i < (fs.Length * 2); i++)
{
fs[i] = i * 10;
if (fs.ErrFlag)
Console.WriteLine("fs[" + i + "] out-of-bounds");
}
for (int i = 0; i < (fs.Length * 2); i++)
{
x = fs[i];
if (!fs.ErrFlag) Console.Write(x + " ");
else
Console.WriteLine("fs[" + i + "] out-of-bounds");
}
Console.ReadLine();
}
}
}
インデクサーを使用して、読み取り/書き込みマルチスレッド同期を非スレッド セーフ ディクショナリ (または非スレッド セーフ コレクション) にエレガントに提供できます。
internal class ThreadSafeIndexerClass
{
public object this[int key]
{
get
{
// Aquire returns IDisposable and does Enter() Exit() on a certain ReaderWriterLockSlim instance
using (_readLock.Aquire())
{
object subset;
_dictionary.TryGetValue(key, out foundValue);
return foundValue;
}
}
set
{
// Aquire returns IDisposable and does Enter() Exit() on a certain ReaderWriterLockSlim instance
using (_writeLock.Aquire())
_dictionary[key] = value;
}
}
}
特に、重い ConcurrentDictionary (またはその他の並行コレクション) を使用したくない場合に便利です。
http://code-kings.blogspot.in/2012/09/indexers-in-c-5.html
システムを使用する;
名前空間 Indexers_Example
{
class Indexers
{
private Int16[] RollNumberVariable;
public Indexers(Int16 size)
{
RollNumberVariable = new Int16[size];
for (int i = 0; i < size; i++)
{
RollNumberVariable[i] = 0;
}
}
public Int16 this[int pos]
{
get
{
return RollNumberVariable[pos];
}
set
{
RollNumberVariable[pos] = value;
}
}
}
}
シーケンスファイルから画像を取得しようとしています。ピクセル値を保持するには、ある種の 2D 配列またはギザギザ配列が必要です。配列の代わりにインデクサーを使用しています。これは、インデクサーをループする方が 2D またはギザギザの配列をループするよりも高速だからです。
@code-kings 投稿への追加。
さらに、呼び出すRollNumberVariable[0]
と、既定のコレクションのインデクサーの動作がトリガーされます。インデクサーは実際にはプロパティですが、データを抽出するときに独自のロジックを作成するのはユーザーの役割です。インデックス パラメータ値のほとんどを簡単に内部コレクションに委譲できますが、特定のインデックス値に対して任意の値を返すこともできます。
ほんの一例 - 2 つ以上の内部コレクションを異なる形式で持つことができますが、外部ユーザーは単一のインデクサー (ディスパッチャーとして機能します) を介してそれらと対話しますが、それらのコレクションは非表示になります。これにより、カプセル化の原則がかなり促進されます。