کنترل دسترسی به اعضای کلاس
Encapsulation در سیشارپ بدین معناست که اطلاعات یک کلاس در برابر دسترسیهای غیرمجاز و خرابکاری محفوظ نگه داشته شود. کلاس که امکان encapsulation را به شما میدهد، دو مزیت عمده دیگر نیز به همراه دارد. اول اینکه دادهها را به کدهای درون کلاس متصل میکند. دوم اینکه دسترسی به اعضای کلاس را کنترل میکند. تا اینجا شما با دو نوع از اعضای کلاس آشنا شدهاید که یکی public بود و دیگری private.
عضوی که public است میتواند آزادانه در خارج از کلاس خودش نیز قابل دسترسی باشد. اعضای private فقط درون همان کلاس قابل دسترسی هستند و البته از طریق یک متد public میتوانند قابل دسترسی و کنترل باشند.
محدود کردن دسترسی به اعضای یک کلاس یکی از بخشهای اساسی برنامهنویسی شیگرا است چراکه از استفادهی نادرست یک شیء جلوگیری میکند. کنترل دسترسی از طریق access modifier ها انجام میشود که public، private، protected و internal هستند. فعلاً به public و private میپردازیم و protected و internal در جای خود توضیح داده میشوند. استفاده بهموقع و بهجا از public و private یکی از نکات مهم و کلیدی برنامهنویسی شیگرا است. در زیر به چند نکته در این مورد اشاره شده:
- آن دسته از اعضای کلاس که فقط در همان کلاس استفاده میشوند باید private باشند.
- دادههایی که باید بین یک محدوده خاص باشند نیز باید private باشند و دسترسی به آنها از طریق یک متد public که بازهی اعداد را بررسی میکند، کنترل شود.
- اگر تغییر دادن یکی از اعضا موجب شود که تاثیر این تغییر از آن عضو فراتر رود (و بر قسمتهای دیگر شیء تاثیر گذارد)، آن عضو باید private باشد و دسترسی به آن باید کنترل شود.
- آن دسته از اعضا که درصورت استفاده نادرست موجب میشوند که شیء آسیب ببینید و آنطور که باید رفتار نکند، باید private باشند و دسترسی به آنها از طریق متدهای public انجام شود تا از استفادهی نادرست آنها جلوگیری شود.
- متدهایی که مقداری را به اعضای private اختصاص میدهند یا مقدار آنها را میخوانند، باید public باشند.
- اگر هیچ دلیلی برای private کردن متغیرهای کلاس نیافتید، میتوانید آنها را public در نظر بگیرید.
البته نکات ظریف دیگری نیز وجود دارندکه در بالا به آنها شاره نکردیم اما در کل اگر همین قوانین را رعایت کنید اشیایی که میسازید بهراحتی خراب نمیشوند و مورد سوءاستفاده قرار نمیگیرند.
برای اینکه درک بهتری از این موارد داشته باشید و بدانید که چرا و چگونه از اینها استفاده میکنیم، مثالی از ساختمان دادهی stack میتواند مفید باشد. یکی از مثالهای مفید برنامهنویسی شیگرا کلاسی است که stack را پیادهسازی و اجرا میکند. همانطور که احتمالاً میدانید، stack ساختاری است برای ذخیره کردن اطلاعات که در آن اولین مقدار ذخیره شده، آخرین مقداری است که مورد استفاده قرار میگیرد. اینطور تصور کنید که تعدادی ظرف را روی میزی (روی هم) قرار دادهاید. اولین ظرفی که روی میز قرار دادید، آخرین ظرفی است که میتوانید آن را بردارید یا برعکس، آخرین ظرفی که گذاشتهاید، اولین ظرفی است که میتوانید آن را بردارید. به این مکانیسم در اصطلاح Last-in, First-out میگویند. کلاسی که ما برای این منظور تعریف میکنیم شامل محلی برای ذخیرهسازی اطلاعات و متدهایی برای کنترل روی این اطلاعات است بنابراین stack درواقع یک data engine است که این اجبار را بهوجود میآورد تا عملیات Last-in, First-out اجرا شود. با این تعاریف نیاز است که یکسری از اعضای کلاس private و یکسری دیگر public باشند تا بتوان مکانیسم Last-in, First-out را اجرا کرد.
یک stack دو عملکرد پایهای را انجام میدهد که عمل push و pop هستند. Push یک مقدار را به بالای stack اضافه میکند و pop یک مقدار را از بالای stack حذف میکند. کلاسی که تعریف خواهیم کرد، شامل یک آرایهی private برای ذخیره سازی اطلاعات و دو متد public که عملیات pop و push را انجام میدهند و Last-in, First-out را پیاده میکنند:
// A stack class for characters class Stack { // These members are private char[] stck; // holds the stack int tos; // index of the top of the stack // Construct an empty Stack given its size. public Stack(int size) { stck = new char[size]; // allocate memory for stack tos = 0; } // Push characters onto the stack public void Push(char ch) { if (tos == stck.Length) { Console.WriteLine("Stack is full!"); return; } stck[tos] = ch; tos++; } // Pop a character from the stack. public char Pop() { if (tos == 0) { Console.WriteLine("Stack is empty!"); return (char)0; } tos--; return stck[tos]; } // Return true if the stack is full. public bool IsFull() { return tos == stck.Length; } // Return true if the stack is empty. public bool IsEmpty() { return tos == 0; } // Return total capacity of the stack. public int Capacity() { return stck.Length; } // Return number of objects currently on the stack. public int GetNum() { return tos; } }
بهتر است به این کلاس دقیقتر نگاه کنیم. کلاس Stack با تعریف این دو instance variables شروع میشود:
// These members are private char[] stck; // holds the stack int tos; // index of the top of the stack
آرایهی stck محلی برای ذخیرهسازی اطلاعات در stack فراهم میکند که این آرایه کاراکتر را در خود نگه میدارد. تخصیص آرایه توسط constructor انجام میگیرد و متغیر tos ایندکس (شماره) بالاترین خانهی stack را در خود نگه میدارد.
هر دو عضو tos و stck بهصورت private هستند و این باعث میشود که مکانیسم Last-in, First-out اجرا شود. اگر دسترسی این دو بهصورت public تعریف شود آنگاه عناصر stack میتوانند خارج از ترتیب قابل دسترسی باشند. همچنین از آنجا که متغیر tos ایندکس بالاترین عنصر stack را نگهداری میکند باید دسترسی به آن محدود شود تا توسط کدهای خارج از کلاس در دسترس و قابل دستکاری و خرابکاری نباشد. البته دسترسی به tos و stck از طریق متدهای public امکانپذیر است.
در خط بعد constructor را میبینید:
// Construct an empty Stack given its size. public Stack(int size) { stck = new char[size]; // allocate memory for stack tos = 0; }
توسط constructor اندازه دلخواه stack مشخص شده و آرایه مورد نظر ساخته میشود. همچنین به متغیر tos مقدار صفر اختصاص مییابد. بنابراین مقدار صفر برای tos مشخص میکند که stack خالی است.
متد ()Push که public تعریف شده، یک عنصر را به stack اضافه میکند:
// Push characters onto the stack public void Push(char ch) { if (tos == stck.Length) { Console.WriteLine("Stack is full!"); return; } stck[tos] = ch; tos++; }
عنصری که قرار است به stack افزوده شود از طریق پارامتر ch وارد stack میشود. البته قبل از اینکه عنصری به stack اضافه شود ابتدا بررسی میشود که stack هنوز خانهی خالی داشته باشد. اینکار با بررسی اینکه tos از طول stck فراتر نرفته باشد انجام میشود. سپس کاراکتر در ایندکسی که tos مشخص میکند ذخیره میشود و در نهایت tos یک واحد افزایش مییابد. بنابراین tos همیشه ایندکس خانهی بعدی stck را در خود نگه میدارد.
برای پاک کردن یک عنصر از stack از متد ()Pop استفاده میکنیم:
// Pop a character from the stack. public char Pop() { if (tos == 0) { Console.WriteLine("Stack is empty!"); return (char)0; } tos--; return stck[tos]; }
در اینجا مقدار tos بررسی میشود، اگر برابر با صفر بود stack خالی است در غیر اینصورت tos یک واحد کاهش مییابد و عنصری که tos به آن اشاره میکند return میشود.
اگرچه ()Push و ()Pop تنها متدهایی هستند که برای اجرای یک stack مورد نیاز است اما تعریف چند متد دیگر نیز میتواند مفید باشد. ما در این کلاس ۴ متد بیشتر تعریف کردهایم که ()IsFull()، IsEmpty()، Capacity و ()GetNum نام دارند و اطلاعاتی را از وضعیت stack به ما میدهند:
// Return true if the stack is full. public bool IsFull() { return tos == stck.Length; } // Return true if the stack is empty. public bool IsEmpty() { return tos == 0; } // Return total capacity of the stack. public int Capacity() { return stck.Length; } // Return number of objects currently on the stack. public int GetNum() { return tos; }
متد ()IsFull هنگامی که stack پر است true برمیگرداند و متد ()IsEmpty هنگامیکه stack خالی است true و هنگامیکه stack خالی نیست false برمیگرداند. برای بدست آوردن ظرفیت کلی stack متد ()Capacity فراخوانی میشود و برای بهدست آوردن تعداد عناصری که در stack ذخیره شدهاند نیز از متد ()GetNum استفاده میشود. دلیل اهمیت این متدها این است که اطلاعات مورد نیاز برای دسترسی به tos را به ما میدهند (با اینکه private است). همچنین این متدها نمونههای خوبی هستند که بدانید چگونه از طریق متدهای public به اعضای private دسترسی و کنترل داشته باشید.
در مرحلهی بعد از این کلاس استفاده میکنیم:
using System; class MyClass { static void Main() { Stack stk1 = new Stack(10); Stack stk2 = new Stack(10); Stack stk3 = new Stack(10); char ch; int i; // Put some characters into stk1. Console.WriteLine("Push A through J onto stk1."); for (i = 0; !stk1.IsFull(); i++) stk1.Push((char)('A' + i)); if (stk1.IsFull()) Console.WriteLine("stk1 is full."); // Display the contents of stk1. Console.Write("Contents of stk1: "); while (!stk1.IsEmpty()) { ch = stk1.Pop(); Console.Write(ch); } Console.WriteLine(); if (stk1.IsEmpty()) Console.WriteLine("stk1 is empty.\n"); // Put more characters into stk1. Console.WriteLine("Again push A through J onto stk1."); for (i = 0; !stk1.IsFull(); i++) stk1.Push((char)('A' + i)); // Now, pop from stk1 and push the element in stk2. // This causes stk2 to hold the elements in reverse order. Console.WriteLine("Now, pop chars from stk1 and push " + "them onto stk2."); while (!stk1.IsEmpty()) { ch = stk1.Pop(); stk2.Push(ch); } Console.Write("Contents of stk2: "); while (!stk2.IsEmpty()) { ch = stk2.Pop(); Console.Write(ch); } Console.WriteLine("\n"); // Put 5 characters into stack. Console.WriteLine("Put 5 characters on stk3."); for (i = 0; i < 5; i++) stk3.Push((char)('A' + i)); Console.WriteLine("Capacity of stk3: " + stk3.Capacity()); Console.WriteLine("Number of objects in stk3: " + stk3.GetNum()); } }
خروجی:
در مثال بعد قصد داریم برنامه دفترچه تلفن سابق را بیشتر شیگرا کنیم. در این دفترچه تلفن یک کلاس برای مخاطب داریم و یک کلاس برای دفترچه تلفن. در کلاس مخاطب، متغیرهای نام، آدرس و شماره تلفن قرار دارد. در کلاس دفترچه تلفن، متدهایی برای جستجو، افزودن مخاطب جدید و نمایش مخاطبان ذخیره شده وجود دارد:
using System; class MainClass { static void Main() { Phonebook myPhonebook = new Phonebook(5); while (true) { Console.Clear(); Console.WriteLine("1. Add"); Console.WriteLine("2. Search By Name"); Console.WriteLine("3. Show all"); Console.WriteLine("4. Exit"); Console.WriteLine(); Console.Write("Choose a number: "); string choice = Console.ReadLine(); switch (choice) { case "1": Console.Clear(); Person contact = new Person( GetString("Please enter your name: "), GetNum("Please enter your number: "), GetString("Please enter your address: ") ); if(myPhonebook.Add(contact)) Console.WriteLine("Your contact added successfully."); else Console.WriteLine("Fail!"); break; case "2": myPhonebook.SearchByName(GetString("Please enter the name: ")); break; case "3": Console.Clear(); myPhonebook.ShowContacts(); break; case "4": Environment.Exit(0); break; default: Console.WriteLine("Invalid Input!"); break; } Console.ReadLine(); } } static string GetString(string message) { Console.Write(message); return Console.ReadLine(); } static int GetNum(string message) { Console.Write(message); return Convert.ToInt32(Console.ReadLine()); } } class Person { string Name; int Number; string Address; public Person(string name, int number, string address) { Name = name; Number = number; Address = address; } public string GetName() { return Name; } public int GetNumber() { return Number; } public string GetAddress() { return Address; } } class Phonebook { Person[] Persons; int Current; bool Found; public Phonebook(int size) { Persons = new Person[size]; Current = 0; } public bool Add(Person person) { if (Current < Persons.Length) { Persons[Current] = person; Current++; return true; } return false; } public void SearchByName(string search) { Found = false; for (int i = 0; i < Persons.Length; i++) { if (Persons[i] == null) break; if (search == Persons[i].GetName()) { Found = true; Console.WriteLine(); Console.WriteLine(Persons[i].GetName() + "\n" + Persons[i].GetNumber() + "\n" + Persons[i].GetAddress()); } } if(!Found) Console.WriteLine("Not Found!"); } public void ShowContacts() { for (int i = 0; i < Persons.Length; i++) { if (Persons[i] == null) return; Console.WriteLine(Persons[i].GetName() + "\n" + Persons[i].GetNumber() + "\n" + Persons[i].GetAddress() + "\n"); } } }
همانطور که میبینید نسبت به قبل از اشیاء و کلاسهای بیشتری استفاده کردیم و این برنامه را بیشتر به سمت شیگرایی سوق دادیم. در کلاس Person سه instance variable تعریف کردهایم که هر سه private و شامل نام، آدرس و شماره تلفن هستند. همچنین از constructor برای مقداردهی به این سه متغیر استفاده کرده و از طریق متدهای public این متغیرها را Read-only کردیم. در کلاس Phonebook آرایهای از جنس کلاس Person داریم. با اینکار در هر خانهی آرایه، یک شیء از جنس Person ذخیره میشود که شامل نام، آدرس و شماره تلفن است. از طریق constructor این کلاس، آرایه ساخته و مقدار دهی میشود. کلاس Phonebook همچنین شامل سه متد برای جستجو، افزودن مخاطب جدید و نمایش مخاطبان ذخیره شده دارد. همانطور که میبینید، متد ()Add یک شیء از جنس Person دریافت میکند و آن را در آرایهای که از جنس Person ساخته بودیم ذخیره میکند و در نهایت اگر با موفقیت مخاطب جدید را ذخیره کرد، مقدار true را باز میگرداند. در متد ()Main برای افزودن مخاطب جدید، یک شیء از کلاس Person ساخته و argument های لازم را به آن دادهایم. سپس متد ()Add را صدا زدهایم تا مخاطب جدید ذخیره شود.
داوود
27 ژانویه 2013
سلام مسعود جان؛
چه عجب!!!!!!!!!!!!!!!!!!
ممنون برای گذاشتن قسمت بیست و چهارم.
sami
28 ژانویه 2013
سلام استاد.همنطور ادامه بدین من از اولین زنگ تا حالا با شما پیش رفتم احساس میکنم شما ما رو درک میکنین و قشنگ جزئیات رو توضیح میدن تا حالا هیچ استادی سرکلاس و یا کتابی اینطور روان و واضح توضیح نداده خواهشا ادامه بدین.
داوود
30 ژانویه 2013
سلام مجدد؛
مسعود جان بحث stack یکم پیچیده است.
میشه گفت که stack نوعی از آرایه است یا بالعکس ؟ آیا خود C# هم دستوراتی برای کار با stack داره یا نه؟
در اینجا که شما گفتید Pop نقش پاک کردن رو برعهده داره یعنی چی؟
من میخواستم که عناصری رو که الان تو stack3 قراردارن رو نمایش بدم و با این تکه کد این کار رو انجام دادم؛ درسته؟
while (!stk3.IsEmpty())
{
ch = stk3.Pop();
Console.Write(ch);
}
[/c#]
پس چه زمانی این متد نقش پاک کردن stack رو اجرا میکنه؟در اینجا که من دارم ازش برای نمایش دادن استفاده می کنم.
این تکه کد به چه معناست؟
return (char)0;
[/c#]
ضمنا از نظر محل قرارگیری در حافظه میدونیم که متغیرهای مقداری در حافظه stack قرار می گیرن! آیا میشه مکان اونها رو تو حافظه دید؟
و اینکه متغیرهای ارجاعی در heap ! درست میگم؟؟
ببخشید از این همه سوال!
مسعود درویشیان
9 فوریه 2013
در اینجا متد ()Pop هم حذف میکنه هم آخرین خونهی stack رو برمیگردونه (که میشه برای نمایش آخرین خونه stack ازش استفاده کرد)
دستور return (char)0 هم وقتی که stack خالی هست اجرا میشه. چون این متد کاراکتر برمیگردونه باید قبلش عملیات cast رو انجام بدیم.
ضمناً در مورد stack و heap توی مقالات آینده یه توضیح کامل میدم.
داوود
9 فوریه 2013
دستت درد نکنه مسعودجان؛ علیرغم این که اینروزها سرت شلوغه ولی ممنون که بازم جواب ما رو دادی.
مرسی
حمید
1 فوریه 2013
سلام
خسته نباشید
ممنون از آموزش ها
ترتیب یک هفته ای درس به هم خورده؟
مهدی
1 فوریه 2013
سلام آقای مهندس؛ احساس می کنم دیگه با علاقه مطالب رو نمیذارید! چرا؟ قرار نبود اینجوری بشه این مطالب درسی از این وبلاگ! ما دلمون به اینجا خوش بود.
مسعود درویشیان
1 فوریه 2013
سلام. نه اینطور نیست نگران نباشید :)
این چند وقت به دلیل یه سری از مشکلات یکم باعث شد تاخیر بیوفته اما این مجموعه تا انتها با موفقیت پیش میره شک نکنید ;)
همینطور برنامهریزی شده بار علمی مقالات از اینی که هست خیلی بره بالاتر
پس اصلاً نگران نباشید
نوید
2 فوریه 2013
سلام آقای مهندس
من هم امیدوارم مقالات به خوبی پیشرفت رو به جلوی داشته باشه و امیدوارم مثل برخی دیگه از فروما نباشه که یه مطلب رو ناقص میذارن و یا به سوالات جواب نمیدن.
f
2 فوریه 2013
سلام.امید وارم که حالتون خوب باشه.دوست عزیز با یادگرفتن این اموزش هایی که شما قرار می دید میشه خارج از محیط وب هم برنامه نوشت؟مثلا برای سیستم عامل اندروید.ممنون از سایت خوبتون.
مسعود درویشیان
3 فوریه 2013
سلام بله میتونید.
حسين
4 فوریه 2013
باید یه تشکر ویژه بکنم از شما آقای درویشیان به خاطر زحماتی که میکشید.
موفق باشی
حمید
8 فوریه 2013
ما منتظریم. شماره بعدی رو کی میزارین؟
ramazan
24 فوریه 2013
اگه امکان داره یه لینک برای دانلود تمام مطالب سی شارپ بذارید
مسعود درویشیان
24 فوریه 2013
لینک دانلود هر قسمت رو توی همون قسمت میتونید ببینید و مقاله رو دریافت کنید.
بعد از به اتمام رسیدن سری آموزشی زنگ سیشارپ، یه لینک واسه دانلود تمام پیدیافها قرار میدیم.
موفق باشید.
محمد فر
7 آوریل 2013
سلام.
منظور از این دستور چیه؟
for (i = 0; !stk1.IsFull(); i++)
stk1.Push((char)(‘A’ + i));
شما در این حلقه برای شرط پایان حلقه مقدار بولی گذاشتید یعنی i از صفر شروع میشه تا مقدار بولی میره؟البته میدونم این حرفم اشتباه.میشه توضیح بدید؟
مسعود درویشیان
7 آوریل 2013
متد ()IsFull یه مقدار بولین برمیگردونه، حلقه تا زمانی اجرا میشه که این مقدار true باشه، به محض اینکه false برگرده برنامه از حلقه خارج میشه
محمد فر
7 آوریل 2013
ببخشید استاد فکر می کنم فهمیدم.این شرط پایانی حلقه است و هر مقداری که جاصلش بولی باشه می تونه در اینجا قرار بگیره!
درسته؟
علیرضا اسکندرپور شوفری
28 آوریل 2013
توی حلقه ی for الزاما در قسمت شرط نباید دو عدد رو بررسی کنیم. البته این ظاهر شرط هست. ما شرط بررسی دو عدد رو که فلانی از فلانی کوچیکتر هست یا نه اینطوری برداشت میکنیم اگه کوچیه که هیچی اگه نه بیخیال. اما ماشین اینطوری میخونه که اون شرط یک مقدار درست یا نادرست داره. (پس ۱<2 درست بر میگردونه و اینجا !stk1.IsFull() هم درست یا نادرت برمیگردونه.) مثل هر حلقه ای وقتی شرط درست نباشه اجرا نمیشه. پس اینطوری به قضیه نگاه کنید که قسمت دوم چه عدد باشه یه تابع باید یک مقدار درست یا نادرست برگردونه.
به عبارتی بله چیزی که شما متوجه شدید درسته. آفرین
Mersad
15 آگوست 2013
سلام
از آموزش های عالیتون بسیـــــــار متشکرم.
شرمنده از اینکه خیلی سوال می پرسم.
میخواستم بدونم ما با چه رویکردی باید کلاس ها رو طراحی کنیم؟
منظورم اینه که ما در طراحی کلاس باید رویکردی کاملا شخصی داشته باشیم و اینجوری فکر کنیم قراره فقط خودمون از این کلاس استفاده کنیم و هرطور که با اون کلاس راحت تریم همونطور طراحیش کنیم، یا اینکه باید رویکرد عمومی داشته باشیم و این رو در نظر داشته باشیم که کسان دیگری هم ممکنه از این کلاس استفاده کن!
این سوالم از این بابته که با این دو رویکرد، خیلی سخته که بفهمیم کدوم متغیر یا متدی رو چه زمانی private یا public تعریف کنیم.
مسعود درویشیان
18 آگوست 2013
هر کلاسی باید یه کار خاص رو انجام بده و باید سعی کنی موقع تعریف یه کلاس، دنیای وافعی در نظر بگیری!
مثلاً یه انسان رو در نظر بگیر. دست یه کلاس اگر باشه، یه سری ویژگیها و یه سری کار انجام میده. اگر پا هم یه کلاس دیگه در نظر بگیری، اون هم یه سری ویژگی و کارهای خاص خودش رو داره. مثلاً اگر جمع شدن زانو رو یه متد در نظر بگیری، آیا این متد هیچ ربطی به کلاس دست داره؟ نه! private در نظر میگیریش ولی مثلاً یه فیلدی توی دست باشه که قراره از مغز فرمان بگیره، یا public در نظر میگیریش یا با یه متد کنترلش میکنی یا با property روش کنترل داری
در کل طوری باشه اگه میدونی یه متد یا فیلد یا هر عضوی از کلاس با بیرون از کلاس نمیخواد ارتباطی داشته باشه، private بگیرش.
باید حالت عمومی در نظر بگیرید که ازش سوء استفاده نشه
Mersad
18 آگوست 2013
متشکرم ازتون
خیلی خوب توضیح دادین
Mersad
15 آگوست 2013
یه سوال دیگه هم داشتم از خدمتتون
میدونم که سوالم چندان در رابطه با موضوع درس نیست، ولی اگه امکانش براتون هست، یه توضیح مختصری راجع به data engine بدین لطفا.
Mersad
15 آگوست 2013
من برنامه ی دفترچه ی تلفن رو با کمی تغییر نسبت به برنامه شما نوشتم. (برنامه شما در این صفحه رو اصلا ندیدم، خودم با آموزش هایی که از همین سلسله مقالات شما یاد گرفته بودم نوشتم و بعدش با جواب شما مقایسه کردم).
میخواستم نظرتون رو بدونم در موردش، لطفا بیرحمانه انتقاد کنید!
مسعود درویشیان
18 آگوست 2013
واقعاً خوبه آفرین :)
محمد
31 آگوست 2014
یه سوال در مورد مثال آخر آیا وقتی یک ر میزنیم و اد فرا خوانی می شه هر بار یک شی ساخته می شه و اون رو تو ماتریس ذخیره می کنه و دوباره که اد رو فراخوانی می کنیم دوباره با همون نام می سازه و استفاده می کنه؟
و آیا دوباره که می سازه قبلی پاک نمی شه و فقط ریفرنس ولیو عوض می شه؟؟؟
و این که این خط
Person[] Persons;
دقیقا چی کار می کنه ؟؟؟این چجور آرایه ایه ؟؟؟ تایپش چیه؟؟؟
می شه ماتریسی ساخت که شی هایی از کلاس های مختلف بگیره؟؟؟ چرا اینارو توضیح ندادین؟
محمد
1 سپتامبر 2014
سوالم گویا نبود؟
esysss
1 سپتامبر 2014
/*******************************
* esysss *
******************************/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
class person
{
string Name;
string Number;
string Adress;
public person(string name, string number, string adress)
{
Name = name;
Adress = adress;
Number = number;
}
public string getname()
{
return Name;
}
public string getnumber()
{
return Number;
}
public string getadress()
{
return Adress;
}
}
class phonebook
{
person[] persons;
int current;
bool found;
public phonebook(int size)
{
persons = new person[size];
current = 0;
}
public bool add(person person)
{
if (current < persons.Length)
{
persons[current] = person;
current++;
return true;
}
return false;
}
public void searchbyname(string search)
{
found = false;
for (int i = 0; i < persons.Length; i++)
{
if (persons[i] == null)
break;
if (search == persons[i].getname())
{
found = true;
Console.WriteLine("OK\nwe found it\n\nname : " + persons[i].getname() + "\tnumber : " + persons[i].getnumber() + "\tadress : " + persons[i].getadress());
}
}
if (!found)
Console.WriteLine("sorry!!!\nnot found");
}
public void showcontacts()
{
for (int i = 0; i < current; i++)
{
if (persons[i].getadress() == null)
break;
Console.WriteLine("\n\n" + persons[i].getname() + "\n" + persons[i].getnumber() + "\n" + persons[i].getadress());
}
}
}
class program
{
static void Main()
{
phonebook myphonebooke = new phonebook(1000);
while (true)
{
Console.Clear();
Console.WriteLine();
Console.WriteLine(" ***********************************");
Console.WriteLine(" * welcome to my new phonebook *");
Console.WriteLine(" * it's awsome *");
Console.WriteLine(" * *");
Console.WriteLine(" * 1-add *");
Console.WriteLine(" * 2-search by name *");
Console.WriteLine(" * 3-show all *");
Console.WriteLine(" * 4-exit *");
Console.WriteLine(" ***********************************");
Console.WriteLine();
Console.WriteLine();
Console.WriteLine("choose a number : ");
string choose = Console.ReadLine();
switch (choose)
{
case "1":
Console.Clear();
person contact = new person(getstring("enter name : "), getstring("enter phone number : "), getstring("enter adress : "));
if (myphonebooke.add(contact))
Console.WriteLine("add sucessfully!!!!!!!!!!");
else
Console.WriteLine("fail");
break;
case "2":
Console.Clear();
myphonebooke.searchbyname(getstring("enter your name to search : "));
break;
case "3":
myphonebooke.showcontacts();
break;
case "4":
Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine("thanks for using\nsee you again\n\nesysss");
Console.ReadKey();
Environment.Exit(0);
break;
default:
Console.WriteLine("please enter right");
break;
}
Console.ReadKey();
}
}
static string getstring(string message)
{
Console.WriteLine(message);
return Console.ReadLine();
}
}
محسن
28 اکتبر 2014
من قصد نوشتن برنامه حسابداری با سی شارپ رو دارم لطفا راهنمایی بفرمایید.