ایندکسرها (Indexers)
با استفاده از ایندکسرها می توان با یک کلاس همانند آرایه ها رفتار کرد. به مثال زیر توجه کنید :
کد:
کد:
using System;
/// <summary>
/// A simple indexer example.
/// </summary>
class IntIndexer
{
private string[] myData;
public IntIndexer(int size)
{
myData = new string[size];
for (int i=0; i < size; i++)
{
myData[i] = "empty";
}
}
public string this[int pos]
{
get
{
return myData[pos];
}
set
{
myData[pos] = value;
}
}
static void Main(string[] args)
{
int size = 10;
IntIndexer myInd = new IntIndexer(size);
myInd[9] = "Some Value";
myInd[3] = "Another Value";
myInd[5] = "Any Value";
Console.WriteLine("\nIndexer Output\n");
for (int i=0; i < size; i++)
{
Console.WriteLine("myInd[{0}]: {1}", i, myInd[i]);
}
}
}
در مثال فوق نحوه ی تعریف و استفاده از ایندکسرها را می توان مشاهده کرد. کلاس IntIndexer حاوی آرایه ای به نام myData می باشد. بدلیل private بودن آن در خارج از کلاس قابل دسترسی نیست. این آرایه در سازنده ی کلاس (متد IntIndexer) با کلمه ی empty مقدار دهی اولیه شده است.
عضو بعدی کلاس Indexer می باشد و با کلمه ی کلیدی this و براکتها مشخص شده ست (this[int pos]). همانطور که ملاحظه می فرمایید نحوه ی تعریف ایندکسرها شبیه به تعریف خواص می باشد.
کد:
کد:
<modifier> <return type> this [argument list]
{
get
{
// Get codes goes here
}
set
{
// Set codes goes here
}
}
خروجی مثال فوق به صورت زیر است :
کد:
کد:
myInd[0]: empty
myInd[1]: empty
myInd[2]: empty
myInd[3]: Another Value
myInd[4]: empty
myInd[5]: Any Value
myInd[6]: empty
myInd[7]: empty
myInd[8]: empty
myInd[9]: Some Value
استفاده از اعداد صحیح روشی است متداول برای دسترسی به اعضای آرایه ها در بسیاری از زبانها اما ایندکسرها در سی شارپ فراتر از این می رود. ایندکسرها را می توان با پارامترهای متعددی تعریف کرد و هر پارامتر با نوعی مختلف (دقیقا همانند پارامترهای ورودی متدها). البته محدودیتی که اینجا وجود دارد در مورد نوع پارامتر ها است که تنها می تواند integers, enums, and strings باشد . بعلاوه قابلیت Overloading ایندکسرها نیز وجود دارد. به همین جهت به آنها آرایه های هوشمند هم گفته می شود (smart arrays) .مثال :
کد:
کد:
using System;
/// <summary>
/// Implements overloaded indexers.
/// </summary>
class OvrIndexer
{
private string[] myData;
private int arrSize;
public OvrIndexer(int size)
{
arrSize = size;
myData = new string[size];
for (int i=0; i < size; i++)
{
myData[i] = "empty";
}
}
public string this[int pos]
{
get
{
return myData[pos];
}
set
{
myData[pos] = value;
}
}
public string this[string data]
{
get
{
int count = 0;
for (int i=0; i < arrSize; i++)
{
if (myData[i] == data)
{
count++;
}
}
return count.ToString();
}
set
{
for (int i=0; i < arrSize; i++)
{
if (myData[i] == data)
{
myData[i] = value;
}
}
}
}
static void Main(string[] args)
{
int size = 10;
OvrIndexer myInd = new OvrIndexer(size);
myInd[9] = "Some Value";
myInd[3] = "Another Value";
myInd[5] = "Any Value";
myInd["empty"] = "no value";
Console.WriteLine("\nIndexer Output\n");
for (int i=0; i < size; i++)
{
Console.WriteLine("myInd[{0}]: {1}", i, myInd[i]);
}
Console.WriteLine("\nNumber of \"no value\" entries: {0}", myInd["no value"]);
}
}
در مثال فوق اولین ایندکسر با یک پارامتر از نوع اعداد صحیح تعریف شده است و در ایندکسر دوم از نوع رشته.
خروجی برنامه ی فوق به صورت زیر است :
کد:
کد:
myInd[0]: no value
myInd[1]: no value
myInd[2]: no value
myInd[3]: Another Value
myInd[4]: no value
myInd[5]: Any Value
myInd[6]: no value
myInd[7]: no value
myInd[8]: no value
myInd[9]: Some Value
Number of "no value" entries: 7
نکته :
1- امضای (لیست پارامترهای) ایندکسر ها در یک کلاس باید منحصر بفرد باشد .
2- تعریف یک ایندکسر به صورت استاتیک مجاز نیست.
در صورت نیاز به ایندکسرهایی با پارمترهای ورودی متعدد می توان به صورت زیر عمل کرد :
کد:
کد:
public object this[int param1, ..., int paramN]
{
get
{
// process and return some class data
}
set
{
// process and assign some class data
}
}
یک مثال دیگر :
کد:
using System;
class IndexExample
{
string Message;
public static void Main()
{
IndexExample obj=new IndexExample("Welcome");
کد:
/* This will access the String variable Message
using array like notation
*/
for(int i=0;i < obj.Length;i++)
{
Console.WriteLine(obj[i]);
}
obj[obj.Length-1]="e to C#";
Console.WriteLine(obj.Message);
}
public IndexExample(string s)
{
Message=s;
}
public string this[int i]
{
get
{
if(i >= 0 && i < Message.Length)
{
return Message.Substring(i,1);
}
else
{
return "";
}
}
set
{
if(i >= 0 && i < Message.Length)
{
Message=Message.Substring(0,i) + value + Message.Substring(i+1);
}
}
}
public int Length
{
get
{
if(Message!=null)
{
return Message.Length;
}
else
return 0;
}
}
}
__________________