C#インデクサーの例をたくさん見てきましたが、実際の状況でどのように役立ちますか。
深刻な機能でなければ、C#の達人がこれを追加しなかったのはわかっていますが、インデクサーを使用する実際の状況(fooバーではない)を考えることはできません。
注: 関連する質問 が存在することに気付きましたが、あまり役に立ちません。
私がインデクサーを見る方法は、(正しいか間違っている!)、インデックスで何かにアクセスする方が他の方法でアクセスするよりも効率的であるということです。 indexを使用すると、その方法でアクセスしたときに値をすばやく検索できます。
古典的な例は配列です。コード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
? writeインデクサー(通常、コレクションのようなクラスを作成しているとき)が必要になることは比較的まれですが、seがかなり頻繁に発生するのではないかと思います。
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番目の学生を指します。
したがって、オブジェクトは、クラスにプライベートまたはパブリックに格納されているInteger変数を参照するインデックス付きの値を取ります。あなたがこの機能を持っていなかったとしたら、おそらくこの方法で参照するでしょう(これはもっと長いでしょう):
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();
}
}
}
ここに私が作成したビデオがあります http://www.youtube.com/watch?v=HdtEQqu0yOY 以下は同じことについての詳細な説明です。
インデクサーは、簡素化されたインターフェイスを使用して、クラス内の包含コレクションにアクセスするのに役立ちます。それは構文上の砂糖です。
たとえば、内部にアドレスコレクションを持つ顧客クラスがあるとします。ここで、「Pincode」と「PhoneNumber」で住所コレクションをフェッチしたいとします。したがって、論理的な手順は、「PhoneNumber」を使用してフェッチするオーバーロード関数と「PinCode」を使用してフェッチする関数の2つのオーバーロード関数を作成することです。以下のコードでは、2つの関数が定義されています。
Customer Customers = new Customer();
Customers.getAddress(1001);
Customers.getAddress("9090");
インデクサーを使用する場合は、以下のコードに示すように、上記のコードを単純化できます。
Customer Customers = new Customer();
Address o = Customers[10001];
o = Customers["4320948"];
乾杯。
シーケンスファイルから画像を取得しようとしています。ピクセル値を保持するには、何らかの2D配列またはギザギザの配列が必要です。 インデクサーを介したループは、2Dまたはギザギザの配列を介したループよりも速いため、配列の代わりにインデクサーを使用しています。
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;
}
}
}
}
インデクサーを使用して、非スレッドセーフディクショナリ(または任意の非スレッドセーフコレクション)への読み取り/書き込みマルチスレッド同期をエレガントに提供できます。
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(またはその他の並行コレクション)を使用したくない場合に役立ちます。
@ code-kings投稿への追加。
さらに、RollNumberVariable[0]
を呼び出すと、デフォルトのコレクションのインデクサーの動作がトリガーされます。 indexersは実際にはpropertiesですが、データを抽出するときに独自のロジックを作成するのはあなたに代わるものです。ほとんどのインデックスパラメータ値を内部コレクションに簡単に委任できますが、特定のインデックス値に対して任意の値を返すこともできます。
単なる例-2つ以上の内部コレクションを異なる形式で持つことができますが、外部ユーザーは単一のインデクサー(ディスパッチャーとして機能します)を介してそれらを操作しますが、これらのコレクションは非表示になります。これにより、カプセル化の原則がかなり促進されます。