نقش Indexer در#C
یکشنبه 20 دی 1394Indexer یک ویژگی پیشرفته در زبان #C است که ما را قادر می سازد که انواع داده ای را به صورت سفارشی بسازیم و دسترسی به بخش های داخلی را با استفاده از syntax ای شبیه به آرایه ایجاد می کند. در این مقاله می خواهیم قابلیت ها و نحوه استفاده از متد Indexer را مورد بررسی قرار دهیم.
مقدمه
زبان C# قابلیتی را فراهم می کند که توسط آن ساختار و کلاس های سفارشی را می توان طراحی کرده که شبیه تعریف یک آرایه استاندارد index شود.
متد Indexer
مهمترین نکاتی که باید در مور دIndexer دانست به صورت زیر است:
Syntax متدهای Indexer
[ access modifier ]< space > [ return type ] < space > this[ parameter-type]
{ get; set; }
مثال:
public string this[string value] { get; set; }
نکته:
Indexer بسیار شبیه Property ها در C# به نظر می رسد، اما کاملا متفاوت است زیرا Indexer یک متد است در حالی که Property ها یک فیلد هستند. حالا اجازه دهید تفاوت های بین Indexer و Property را توضیح دهیم:
Indexer توسط یک signature تعریف می شود در حالی که property توسط نام آن تعریف می شود.
یک property می تواند یک عضو استاتیک باشد در حالی که یک Indexer همیشه یک نمونه(instance) است.
هیچ نامی برای متد Indexer وجود ندارد و یا توسط نوع کلاس، ساختار یا interface خود شناخته می شوند.
در محل نام متد، کلمه کلیدی this با عملگر [] باید وجود داشته باشد.
به یاد داشته باشید:
که توسط قرارداد indexer یک متد است اما خیلی با یک متد یا تابع معمولی متفاوت است زیرا indexer باید حداقل یک پارامتر داشته باشد و دو متد indexer از یک کلاس نمی توانند پارامترهای مشابه داشته باشد.
فرض کنید ما یک متد Indexer با یک پارامتر از نوع integer داریم پس نمی توانیم متد دیگری با همان نوع و پارامتر را اعلان کنیم.
اگر چندین متد با نوع پارامترهای مشابه اضافه کنیم ، در زمان کامپایل خطا نشان خواهد داد. Indexer در مورد نوع بازگشتی اهمیتی نمی دهد، نوع بازگشتی آن ممکن است شبیه یا متفاوت باشد اما پارامترها به هیچ وجه مشابه نیستند. تصویر زیر برنامه ای را نشان می دهد که در آن تلاش می کنیم پارامترهای دو متد indexer را با نوع مشابه استفاده کنیم .ولی خطا می دهد که " در حال حاضر یک عضو فراخوانی شده با کلمه کلیدی this با نام های مشابه تعریف شده است.
مثال:
private List<People> myContactList = new List<People>(); myContactList.Add(new People("Ram", "ram@yahoo.com", "9797225566", "New Delhi")); myContactList.Add(new People("Shyam", "shyam@gmail.com", "8484225599", "Mumbai")); myContactList.Add(new People("Rajesh", "rajesh@yahoo.com", "8888225458", "New Delhi")); myContactList.Add(new People("Dilip", "dilip@facebook.com", "7777225522", "New Delhi")); myContactList.Add(new People("Rama", "rama@yahoo.com", "9718185511", "Delhi"));
در قطعه کد بالا ما پنج رکورد ساختگی به یک لیست اضافه کرده ایم.
private List < People > myContactList = new List < People > (); public People this[string peopleName] { get { foreach(People p in myContactList) { if (p.FullName.ToLower() == peopleName.ToLower()) { peopleDetail = new People(p.FullName, p.Email, p.Contact, p.City); break; } } return peopleDetail; } }
قطعه کد بالا یک مثال برای متد Indexer است که جزئیات افراد را توسط نام آنها پیدا می کند. این متد در نتایج جستجو فقط یک شخص را بر می گرداند که با لیست افراد مطابقت دارد اما قطعه کدی که در زیر ذکر شده لیستی از افراد که نام مشابه دارند را نیز برمی گرداند. برای مثال Name==Ram
private List<People> searchResultList = new List<People>(); public List<People> this[string peopleName] { get { foreach (People p in myContactList) { if (p.FullName.ToLower()==peopleName.ToLower()) { searchResultList.Add(p); } } return searchResultList; } }
پیاده سازی واقعی متدهای Indexer
اجازه دهید یک اپلیکیشن برای شناخت پیاده سازی واقعی متد Indexer ایجاد کنیم. در ادامه با پیاده سازی متدهای Indexer در Console Application و Web Application آشنا خواهیم شد. بنابراین ابتدا می خواهیم یک پروژه از نوع class library ایجاد کنیم که تمام منطق متدهای Indexer ما را نگه می دارد سپس از همان منطق در هردو اپلیکیشن با رفرنس دادن فایل های dll استفاده می کنیم.
Class Library
حالا می خواهیم یک پروژه از نوع class library ایجاد کنیم که به ما کمک می کند همان منطق را در اپلیکیشن های متفاوت استفاده کنیم. چرا که در این مقاله این Library Project را با اپلیکیشن های زیر استفاده خواهیم کرد:
Console Application
Web Application
مرحله 1: یک پروژه class library با نام People and Phonebook ایجاد کنید. برای ایجاد این پروژه باید مراحل زیر را انجام دهیم:
مرحله 2: حالا یک کلاس People اضافه کرده و Property های زیر را داخل کلاس People می نویسیم.
//Class public class People { public string FullName { get; set; } public string Email { get; set; } public string Contact { get; set; } public string City { get; set; } public People(string fullName, string email, string contact, string city) { FullName = fullName; Email = email; Contact = contact; City = city; } }
حالا کلاس دیگری با نام Phonebook اضافه می کنیم زیرا در این اپلیکیشن از متد indexer برای جستجوی شماره تماس در یک دفترچه تلفن استفاده می کنیم که شامل لیستی از افراد با نام، تلفن تماس، ایمیل و شهر آنها می باشد.
public class Phonebook { private List<People> myContactList = new List<People>(); private List<People> searchResultList = new List<People>(); People peopleDetail; public Phonebook() { myContactList.Add(new People("Ram", "ram@yahoo.com", "9797225566", "New Delhi")); myContactList.Add(new People("Shyam", "shyam@gmail.com", "8484225599", "Mumbai")); myContactList.Add(new People("Rajesh", "rajesh@yahoo.com", "8888225458", "New Delhi")); myContactList.Add(new People("Dilip", "dilip@facebook.com", "7777225522", "New Delhi")); myContactList.Add(new People("Rama", "rama@yahoo.com", "9718185511", "Delhi")); } }
در قطعه کد بالا ما یک کلاس با نام Phonebook ایجاد کرده بودیم که در آن 5 رکورد اضافه شده بود. برای اضافه کردن این رکورد این کد را در سازنده پیش فرض از کلاس Phonebook می نویسیم بنابراین ما نمونه ای از کلاس را ایجاد کردیم که این 5 رکورد را به آن اضافه خواهد کرد.
در کد بالا یک شیئ ایجاد کردیم که نام آن myContactList بوده و از نوع< list<people می باشد وهمچنین 5 رکورد ساختگی اضافه شده به این مجموعه نیز وجود دارد.حالا می خواهیم متدهای Indexer را برای دسترسی به لیست شماره تماس ها طبق متدهای indexer خود بنویسیم.
1. یک متد Indexer در کلاس Phonebook برای نمایش تمام لیست اضافه می کنیم.
//1. Indexer Method: To show all records public List < People > this[bool isShowAll] { get { if (isShowAll == true) { foreach(People p in myContactList) { searchResultList.Add(p); } } return searchResultList; } }
در کد بالا یک متد indexer از نوع Boolean اضافه کرده ایم. طبق این کد اگر ما پارامتری را به صورت True ارسال کنیم آنگاه این متد تمام رکوردهای در دسترس در این phone-book را نشان می دهد و در غیر این صورت چیزی ا نشان نمی دهد.
2. متد Indexer دیگری برای یافتن شماره تماس توسط نام شخص، اضافه می کنیم.
public class Phonebook { private List < People > searchResultList = new List < People > (); private List < People > myContactList = new List < People > (); //2. Indexer Method: To show record by name public People this[string peopleName] { get { foreach(People p in myContactList) { if (p.FullName.ToLower() == peopleName.ToLower()) { peopleDetail = new People(p.FullName, p.Email, p.Contact, p.City); break; } } return peopleDetail; } } }
این متد Indexer رکوردی را نمایش می دهد که نام آن دقیقا مطابق با پارامتر ورودی باشد و در غیر این صورت چیزی را نشان نمی دهد.
3. متد Indexer دیگری برای جستجوی یک رکورد توسط نام یا شهر شخص اضافه ی کنیم.
public class Phonebook { private List < People > searchResultList = new List < People > (); private List < People > myContactList = new List < People > (); //3. Indexer Method: To show record by match by name or city public List < People > this[string peopleName, string cityName] { get { foreach(People p in myContactList) { if (p.FullName.Contains(peopleName)) { searchResultList.Add(p); } else if (p.City.Contains(cityName)) { searchResultList.Add(p); } } return searchResultList; } } }
حالا project library شما برای استفاده آماده است. تصویر زیر قطعه کد کاملی است که داخل این project library نوشته شده است.
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace MyPhonebook { //Class public class People { public string FullName { get; set; } public string Email { get; set; } public string Contact { get; set; } public string City { get; set; } public People(string fullName, string email, string contact, string city) { FullName = fullName; Email = email; Contact = contact; City = city; } } //Class public class Phonebook { private List<People> myContactList = new List<People>(); private List<People> searchResultList = new List<People>(); People peopleDetail; public Phonebook() { myContactList.Add(new People("Ram", "ram@yahoo.com", "9797225566", "New Delhi")); myContactList.Add(new People("Shyam", "shyam@gmail.com", "8484225599", "Mumbai")); myContactList.Add(new People("Rajesh", "rajesh@yahoo.com", "8888225458", "New Delhi")); myContactList.Add(new People("Dilip", "dilip@facebook.com", "7777225522", "New Delhi")); myContactList.Add(new People("Rama", "rama@yahoo.com", "9718185511", "Delhi")); } /// <summary> /// Display all contacts list /// </summary> /// <param name="peopleName"></param> /// <returns></returns> public List<People> this[bool isShowAll] { get { if (isShowAll == true) { foreach (People p in myContactList) { searchResultList.Add(p); } } return searchResultList; } } /// <summary> /// Searching by Name (By Exact match) /// </summary> /// <param name="peopleName"></param> /// <returns></returns> public People this[string peopleName] { get { foreach (People p in myContactList) { if (p.FullName.ToLower() == peopleName.ToLower()) { peopleDetail = new People(p.FullName, p.Email, p.Contact, p.City); break; } } return peopleDetail; } } /// <summary> /// Serching by Name or City (Returns exact macth or not) /// </summary> /// <param name="name"></param> /// <param name="cityName"></param> /// <returns></returns> public List<People> this[string peopleName, string cityName] { get { foreach (People p in myContactList) { if (p.FullName.Contains(peopleName)) { searchResultList.Add(p); } else if (p.City.Contains(cityName)) { searchResultList.Add(p); } } return searchResultList; } } } }
Web Application
حالا می خواهیم یک وب سایت ایجاد کنیم که رفرنس همان کتابخانه که از قبل تعریف کرده ایم را در آن قرار داده ایم که توسط متد indexer در web application شناخته شود.
در ابتدا می خواهیم یک وب سایت به solution اضافه کنیم و رفرنس MyPhonebook.dll را توسط راست کلیک بر روی وب سایت ایجاد کنیم. که بر روی Add Reference... از popup پنجره کلیک کرده و بعد آن یک پنجره جدید ظاهر می شود که می تواند فایل library .dll را پیدا و انتخاب کند.
حالا نیاز داریم که یک صفحه وب اضافه کنیم که در آن متدهای Indexer را جهت نشان دادن نتایج برای هر نوع فراخوانی خواهیم کرد. فرض کنید یک صفحه Default.aspx در web application داریم. و کد زیر را داخل تگ <form> اضافه می کنیم:
<form id="form1" runat="server"> <div class="main-box"> <h2>Indexer Method</h2> <p>Demo Application</p> <br /> <div class="Filter"> <asp:Button ID="btnAll" runat="server" CssClass="button" Text="All" OnClick="btnAll_Click"></asp:Button> <asp:Button ID="btnByName" runat="server" CssClass="button" Text="By Name" OnClick="btnByName_Click"></asp:Button> <asp:Button ID="btnByBoth" runat="server" CssClass="button" Text="Name & City" OnClick="btnByBoth_Click"></asp:Button> </div> <br style="clear: both;" /> <table class="searchBox"> <tr id="panelSearchByName" runat="server" visible="false"> <td> <asp:TextBox ID="txtSerchByName" runat="server" placeholder="Name"></asp:TextBox> <asp:Button ID="btnSearchByName" runat="server" Text="Go" OnClick="btnSearchByName_Click" /> </td> </tr> <tr id="panelSearchByNameandCity" runat="server" visible="false"> <td> <asp:TextBox ID="TextBoxName" runat="server" placeholder="Name"></asp:TextBox> <asp:TextBox ID="TextBoxCity" runat="server" placeholder="City"></asp:TextBox> <asp:Button ID="btnByNameAndCity" OnClick="btnByNameAndCity_Click" runat="server" Text="Go" /> </td> </tr> </table> <p id="headingText" runat="server">All Contacts</p> <asp:Repeater ID="GridViewPhonebook" runat="server"> <ItemTemplate> <div class="record-list"> <img src="" alt="People Photo" /> <div class="right"> <span class="name"><%# DataBinder.Eval(Container.DataItem,"FullName") %></span> <span class="mobile"><%# DataBinder.Eval(Container.DataItem,"Contact") %></span> <span class="email"><%# DataBinder.Eval(Container.DataItem,"Email") %></span> <span class="city"><%# DataBinder.Eval(Container.DataItem,"City") %> </span> </div> </div> </ItemTemplate> </asp:Repeater> <asp:Label ID="Message" runat="server" Text="No Record Found" ForeColor="Red" Visible="false"></asp:Label> </div> </form>
برای نمایش لیست تمام رکوردها متد زیر را در صفحه Default.aspx.cs می نویسیم تا تمام رکورد های لیست را نشان دهد و این متد را در رویداد Page_Load فراخوانی می کند:
private void BindAllContact() { List < People > myPhonebookList = phonebook[true]; if (myPhonebookList != null) { DataTable dataTable = new DataTable(); dataTable.Columns.Add("FullName"); dataTable.Columns.Add("Email"); dataTable.Columns.Add("Contact"); dataTable.Columns.Add("City"); foreach(People people in myPhonebookList) { dataTable.Rows.Add(people.FullName, people.Email, people.Contact, people.City); } GridViewPhonebook.DataSource = dataTable; GridViewPhonebook.DataBind(); headingText.InnerText = "All Contact"; Message.Visible = false; } else { Message.Visible = true; } }
متد بالا متد indexer را فراخوانی می کند که یک پارامتر از نوع boolean را طبق منطق ما که داخل متد indexer نوشته شده بود می پذیرد.اگر پارامتر را به صورت True ارسال کنید به تمام رکوردهای موجود را نشان داده و در غیر این صورت چیزی نشان نمی دهد.
حالا متد ( )BindAllContact را روی Page_Load فراخوانی می کنیم.که لیست رکوردها را مانند زیر نمایش خواهد داد. تصویر زیر لیستی از تمام رکوردهای در دسترس در این phonebook را نشان می دهد:
در این صفحه ما سه دکمه زیر را اضافه می کنیم که طبق متدهای indexer ما می باشد.
ALL: این متد تمام رکوردها را نشان می دهد.
by name : این متد رکوردهایی که نام آنها دقیقا مطابق است را نشان می دهد.
by name & city : این متد تمام رکوردهایی که مطابق با نام یا شهر باشند را نشان می دهد.
جستجو توسط نام
حالا متد های زیر را به Default.aspx.cs اضافه کرده و این متد را روی رویداد Button_Click ای فراخوانی می کنیم که شما می خواهید لیست نتایج را در آن نشان دهید. برای این مقاله ما این متد را روی کلیک دکمه Go فراخوانی خواهیم کرد.
private void BindListByName(People people) { headingText.InnerText = "Search Result"; if (people != null) { DataTable dataTable = new DataTable(); dataTable.Columns.Add("FullName"); dataTable.Columns.Add("Email"); dataTable.Columns.Add("Contact"); dataTable.Columns.Add("City"); dataTable.Rows.Add(people.FullName, people.Email, people.Contact, people.City); GridViewPhonebook.DataSource = dataTable; GridViewPhonebook.DataBind(); Message.Visible = false; } else { GridViewPhonebook.DataSource = null; GridViewPhonebook.DataBind(); Message.Visible = true; } }
نتیجه جستجوی خروجی:
جستجو توسط نام وشهر:
حالا متدها را به Default.aspx.cs اضافه کرده و این متد را روی Button_Click ای فراخوانی می کنیم که می خواهیم نتایج در آن نشان داده شود.
private void BindListByNameAndCity(List < People > people) { headingText.InnerText = "Search Result"; if (people != null) { DataTable dataTable = new DataTable(); dataTable.Columns.Add("FullName"); dataTable.Columns.Add("Email"); dataTable.Columns.Add("Contact"); dataTable.Columns.Add("City"); foreach(People p in people) { dataTable.Rows.Add(p.FullName, p.Email, p.Contact, p.City); } GridViewPhonebook.DataSource = dataTable; GridViewPhonebook.DataBind(); Message.Visible = false; } else { GridViewPhonebook.DataSource = null; GridViewPhonebook.DataBind(); Message.Visible = true; } }
پنجره نتیجه جستجو:
Console Application
حالا می خواهیم یک console application ایجاد کنیم که از class library برای نمایش متدهای Indexer استفاده می کنیم.
مرحل 1: یک console application ایجاد می کنیم یا یک پروژه جدید به solution اضافه می کنیم.
مرحله 2: حالا class library project در این console application ارجاع داده و برای انجام این کار مراحل زیر را دنبال می کنیم. راست کلیک بر روی نام پروژه و Add Reference... را انتخاب کرده و library project را جستجو می کنیم.
حالا پنجره زیر را در جایی که پروژه خود را انتخاب می کنیم می بینیم.
حالا می توانیم کتابخانه پروژه خود را با نام MyPhonebook مشاهده کنیم که در قسمت دایرکتوری references لیست شده است.
حالا متد Indexer را برای نمایش تمام رکوردها فراخوانی می کنیم که در phonebook در دسترس است.
{ static void Main(string[] args) { Phonebook myPhonebook = new Phonebook(); List < People > allPeople = myPhonebook[true]; if (allPeople != null) { foreach(People p in allPeople) { Console.WriteLine("Name: {0},\nE-mail:{1},\nContact: {2}, \nCity: {3}", p.FullName, p.Email, p.Contact, p.City); Console.WriteLine("\n........"); } } else { Console.WriteLine("\n No Contact Found."); } Console.ReadLine(); } }
خروجی:
حالا متد indexer را برای جستجوی رکوردی فراخوانی کنیم که نام آن Ram است:
حالا می خواهیم متد indexer را برای جستجوی رکوردی با نام Ram و شهر Delhi فراخوانی کنیم:
نتیجه جستجو در حالت Debug:
- C#.net
- 2k بازدید
- 3 تشکر