آموزش سی شارپ c# درس یازدهم

 
ارسال شده در تاریخ 1392/7/22 توسط admin در زمینه آموزش سی شارپ
 
درس یازدهم - اندیسها در (Indexers) C#
 
در این درس با اندیکسرها در C# آشنا میشویم . اهداف این درس به شرح زیر می باشند :
• پی ادهسازی اندیکسر
• سرریزی اندیکسرها (Overload)
• دری چگونگی پیاده سازی اندیکسرهای چند پارامتری
• خلاصه
• نکات مهم و مطالب کمکی در زمینه اندیکسرها
 
اندیکسرها
اندیکسرها مفهومی بسیار ساده در زبان C# هستند . با استفاد ه از آنها می توانید از کلاس خود همانند یک آرایه استفاده کنید . در داخل کلاس مجمو عه ای از مقادیر را به هر طریقی که مورد نظرتان هست مدیریت کن ید . این اشیاو می توانند شامل مجموع ه ای از اعضای کلاس، یک آرایه دیگر، و یا مجمو عه ای از ساختارهای پیچیده داده ای باشند، جدا از پیاده سازی داخلی کلاس، داده های این ساختارها از طریق استفاده از اندیکسرها قابل دسترسی هستند . به مثالی در این زمینه توجه کنید :
 
مثال : 1-11 نمونهای از یک اندیکسر
using System; ///
مثالی ساده از یک اندیکسر ///
/// 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(" Indexer Output "); for (int i=0; i < size; i++)
{
Console.WriteLine("myInd[{0}]: {1}", i, myInd[i]);
}
}
}
مثال 1-11 نحوه پیاده سازی اندیکسر را نشان می دهد . کلاس IntIndexer دارای آرایه رشته ای بنام myData می باشد . این آرایه، عنصری خصوصی (private) است و کاربران خارجی (external users) نمی توانند به آن دسترسی داشته باشن د . این
آرایه درون سازنده (constructor) کلاس تخصیص دهی می گردد که در آن پارامتر size از نوع int دریافت می شود، از آرایه myData نمونه ای جدید ایجاد میگردد، سپس هر یک از المانهای آن با کلمه "empty" مقدار دهی می گردد .
 
عضو بعدی کلاس، اندیکسر است که بوسیله کلمه کلیدی this و دو براکت تعریف شده است، .this[int pos] این اندیکسر پارامتر موقعیتی pos را دریافت می نماید . همانطور که حتماً تا کنون دریافته اید پی ادهسازی اندیکسر بسیار شبیه به پیاده سازی یک ویژگی
(property) است . اندیکسر نیز دارای accessor های set و get است که دقیقاً همانند property عمل می کنند . همانطور که در اعلان این اندیکسر نیز مشاهده می شود، متغیری از نوع رشتهای را باز می گرداند .
 
در متد Main() شیء جدیدی از IntIndexer ایجاد شده است و مقادیری به آن افزوده می شود و سپس نتایج چاپ می گردند . خروجی این برنامه به شکل زیر است :
Indexer Output 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
 
استفاده از integer جهت دسترسی به آرایه ها در اغلب زبانهای برنامه سازی رایج است ولی زبان C# چیزی فراتر از آنرا نیز پشتیبانی می کند . در C# اندیکسرها را می توان با چندین پارامتر تعریف کرد و هر پارامتر می تواند از نوع خاصی باشد . پارا مترهای مختلف بوسیله کاما از یکدیگر جدا می شوند . پارامترهای مجاز برای اندیکسر عبارتند از integer : ، enum و .string علاوه بر آن، اندیکسرها قابل سرریزی (Overload) هستند . در مثال 11-2 تغییراتی در مثال قبل ایجاد کرده ایم تا برنامه قابلیت دریافت اندیکسرهای سرریز شده را نیز داشته باشد .
 
www.Cporoje.ir
 
سرریزی اندیکسرها
مثال : 11-2 اندیکسرهای سرریز شده (Overloaded Indexers)
using System; ///
پی ادهسازی اندیکسرهای سرریز شده ///
/// 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"; }//end of for
}//end of constructor
 
public string this[int pos]
{ get
{
return myData[pos];
} set
{
myData[pos] = value;
}
}//end of indexer
 
public string this[string data]
{ get
{
int count = 0;
for (int i=0; i < arrSize; i++)
{
if (myData[i] == data)
{
count++; }//end of if }//end of for
 
 return count.ToString(); }//end of get set
{
for (int i=0; i < arrSize; i++)
{
if (myData[i] == data)
{
myData[i] = value; }//end of if }//end of for }//end of set
}//end of overloaded indexer
 
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(" Indexer Output "); for (int i=0; i < size; i++)
{
Console.WriteLine("myInd[{0}]: {1}", i, myInd[i]); }//end of for
Console.WriteLine(" Number of "no value" entries: {0}", myInd["no value"]); }//end of Main() }//end of class
 
 
مثال 11-2 نحوه سرریز کردن اندیکسر را نشان می دهد . اولین اندیکسر که دارای پارامتری از نوع int تحت عنوان pos است دقیقاً مشابه مثال 11-1 است ولی در اینجا اندیکسر جدیدی نیز وجود دارد که پارامتری از نوع string دریافت می کند get accessor . اندیکسر جدید رشتهای را ب رمیگرداند که نمایشی از تعداد آیتمهایی است که با پارامتر مقداری data مطابقت می کند set .
accessor مقدار هر یک از مقادیر ورودی آرایه را که مقدارش با پارامتر data مطابقت نماید را به مقداری که به اندیکسر تخصیص داده می شود، تغییر میدهد .
 www.IranProje.com
رفتار (behavior) اندیکسر سرریز شده که پارامتری از نوع string دریافت می کند، در متد Main() نشان داده شده است . در اینجا set accessor مقدار "No value" را به تمام اعضای کلاس myInd که مقدارشان برابر با "empty" بوده است، تخصیص میدهد . این accessor از دستور زیر استفاده نموده است . myInd["empty"] = "No value" : پس از اینکه تمامی اعضای کلاس myInd چاپ شدند، تعداد اعضایی که حاوی "No value" بوده اند نیز نمایش داده می شوند . این امر با استفاده از دستور زیر در get accessor روی میدهد .myInd["No value"] : خروجی برنامه بشکل زیر است :
Indexer Output
 
 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
 
علت همزیستی هر دو اندیکسر در مثال 11-2 در یک کلاس مشابه، تفاوت اثرگذاری و فعالیت آنهاست . اثرگذاری و تفاوت اندیکسرها از تعداد و نوع پارامترهای موجود در لیست پارامترهای اندیکسر مشخص می گردد . در هنگام استفاده از اندیکسرها نیز، کلاس با استفاده از تعداد و نوع پارامترهای اندیکسر ها، میتواند تشخیص دهد که در یک فراخوانی از کدام اندیکسر باید استفاده نماید . نمونه ای از پی ادهسازی اندیکسری با چند نوع پارامتر در زیر آورده شده است :
public object this[int param1, ..., int paramN]
{ get
{
// process and return some class data
} set
{
// process and assign some class data
}
}
خلاصه :
هم اکنون شما با اندیکسرها و نحوه پیاده سازی آنها آشنا شده اید . با استفاده از اندیکسرها می توان به عناصر یک کلاس همانند یک آرایه دسترسی پیدا کرد . در این مبحث اندیکسرهای سرریز شده و چند پارامتری نیز مورد بررسی قرار گرفتند . در آینده و در مباحث پیشرفته تر با موارد بیشتری از استفاده اندیکسرها آشنا خواهید شد .
 
نکات :
.1 منظور از اندیکسر سرریز شده چیست؟
هنگامیکه از دو یا چند اندیکسر درون یک کلاس استفاده می کنیم، سرریزی (Overloading) اندیکسرها رخ می دهد . در هنگام فراخ وانی اندیکسرها، کلاس تنها از روی نوع بازگشتی اندیکسر و تعداد پارامترهای آن متوجه می شود که منظور فراخواننده استفاده از کدام اندیسکر بوده است .
 
.2 از اندیکسر چگونه مانند آرایه استفاده می شود؟
همانطور که در این درس مشاهده کردید دسترسی به عناصر اندیکسر همانند آرایه ها با استفاده از یک اندیس صورت میپذیرد . با استفاده از این اندیس میتوان به عنصر مورد نظر کلاس دسترسی پیدا نمود .
 
 
www.IranProje.com
.3 یک مثال عملی استفاده از اندیکسرها چیست؟
یک نمونه بسیار جالب از استفاده اندیکسرها کنترل ListBox است ListBox) . عنصری است کنترلی که با استفاده از آن لیستی از عناصر رشتهای نمایش داده میشوند و کاربر با انتخاب یکی از این گزینه ها با برنامه ارتباط برقرار می کند . در حقیقت این عنصر کنترلی یکی از روشهای دریافت اطلاعات از کاربر است با این تفاوت که در این روش ورودی هایی که کاربر میتواند وارد نماید محدود شده هستند و از قبل تعیین شده اند . نمونه ای از یک ListBox قسمت انتخاب نوع فونت در برنامه Word است که در آن لیستی از فونتهای موجود در سیستم نمایش داده می شود و کاربر با انتخاب یکی از آنها به برنامه اع لام میکند که قصد استفاده از کدام فونت سیستم را دارد ListBox (. نمایشی از ساختمان داده ایست شبیه به آرایه که اعضای آن
همگی از نوع string هستند . علاوه بر این این کنترل می خواهد تا در هنگام انتخاب یکی از گزین ه هایش بتواند اطلاعات خود را بطور خودکار update نماید و یا به عبارتی بتواند ورودی دریافت نمای د . تمامی این اهداف با استفاده از اندیکسر میسر می شود . اندیکسرها شبیه به property ها اعلان می شوند با این تفاوت مهم که اندیکسرها بدون نام هستند و نام آنها تنها کلمه کلیدی this است و همین this مورد اندیکس شدن قرار می گیرد و سایر موارد بشکل پارامتر به اندیکسر داده میشوند .
public class ListBox: Control
{
private string[] items;
 
public string this[int index]
{ get
{
return items[index];
} set
{
items[index] = value; Repaint();
}
}
}
با نگاه به نحوه استفاده از اندیکسر بهتر می توان با مفهوم آن آشنا شد . برای مثال دسترسی به ListBox بشکل زیر است :
ListBox listBox = ...; listBox[0] = "hello";
Console.WriteLine(listBox[0]);
 
نمونه برنامه ای که در آن نحوه استفاده از اندیکسر در عنصر کنترلی ListBox نشان داده شده، در زیر آورده شده است :
 
Csharp-Persian_Indexer_Demo
 
using System;
 
public class ListBoxTest
{
رشته های مورد نظر به ListBox تخصیص داده میشوند //.
public ListBoxTest(params string[] initialStrings)
 
 
{
فضایی را برای ذخیره سازی رشته های تخصیص می دهد // .
strings = new String[256];
رشته های وارد شده به سازنده را درون آرایه ای کپی می کند // .
foreach (string s in initialStrings)
{
strings[ctr++] = s;
}
}//end of constructor
 
رشتهای به انتهای کنترل افزوده می شود // .
public void Add(string theString)
{
if (ctr >= strings.Length)
{
در این قسمت میتوان کدی جهت کنترل پر شدن فضای تخصیص داده شده قرار داد // .
} else
strings[ctr++] = theString; }//end of Add()
 
اعلان اندیکسر //
public string this[int index]
{ get
{
if (index < 0 || index >= strings.Length)
{
در این قسمت میتوان کدی جهت کنترل پر شدن فضای تخصیص داده شده قرار داد // .
}
return strings[index]; }//end of get set
{
if (index >= ctr )
{
فراخوانی متدی جهت کنترل خطا //
} else
strings[index] = value; }//end of set }//end of indexer
 
تعداد رشته های موجود را نشان میدهد //
public int GetNumEntries( )
 
 
{
return ctr;
}
 
private string[] strings; private int ctr = 0;
}//end of ListBoxTest class
 
public class Tester
{
static void Main( )
{
ساخت یک ListBox جدید و تخصیص دهی آن //
ListBoxTest lbt = new ListBoxTest("Hello", "World");
رشته های مورد نظر به کنترل افزوده میشوند // .
lbt.Add("Who"); lbt.Add("Is"); lbt.Add("John"); lbt.Add("Galt");
رشته جدیدی در خانه شماره یک فرار داده می شود // .
string subst = "Universe"; lbt[1] = subst;
کلیه آیتمهای موجود نمایش داده می شوند // .
for (int i = 0;i
{
Console.WriteLine("lbt[{0}]: {1}",i,lbt[i]);
}
}//end of Main() }//end of Tester class
خروجی نیز بشکل زیر می باشد :
 
Output:
 
lbt[0]: Hello lbt[1]: Universe lbt[2]: Who lbt[3]: Is lbt[4]: John lbt[5]: Galt
 
توجه :
مطالب انتهایی این درس کمی پیشرفت ه تر و پ یچیده تر از مطالب قبل به نظر می آیند . این انتظار وجود ندارد که شما کلیه مطالب این قسمت را بطور کامل متوجه شده باشید، بلکه هدف تنها آشنا شدن شما با مسایل پیچیده تر و واقعی تر است . در آینده ای نه چندان دور، در سایت به صورت حرف ه ای کلیه مطالب و سرفصل های گفته شده را مورد بررسی قرار خواهیم داد . در ابتدا هدف من
 
 
آشنایی شما با کلیه مفاهیم پای ه ای زبان C# است تا بعد از این آشنایی به طور کامل و بسیار پیشرفته به بررسی کلیه مفاهیم زبان بپردازیم . پس از اتمام آموزش اولیه تحولات اساسی در سایت مشاهده خواهید کرد و در آن هن گام به بررسی کامل هر مبحث با مثال هایی بسیار واقعی و کاربردی خواهیم پرداخت .

www.IranProje.com

Copyright © 2014 icbc.ir