رفتن به مطلب



iran rules jazbe modir
ADS mahak

Doctor Robot

 مدیر انجمن
  • تعداد ارسال ها

    3,261
  • امتیاز

    14,824 
  • تاریخ عضویت

  • آخرین بازدید

  • روز های برد

    54

تمامی مطالب نوشته شده توسط Doctor Robot

  1. Doctor Robot

    Programming-Py python Gui

    دوستان سلام وقت بخیر آموزش برنامه نویسی پایتون گرافیکی به اتمام رسید
  2. Doctor Robot

    Programming-Py python Gui

    filedialog پکیج filedialog دارای توابعی جهت باز کردن فایل و پوشه و همچنین ذخیره فایل‌ها می‌باشد. در جدول زیر لیست این توابع ذکر شده است: حال به بررسی نحوه استفاده از توابع فوق می‌پردازیم و ابتدا ()askdirectory: 1 import tkinter 2 from tkinter import * 3 from tkinter import filedialog 4 5 window = tkinter.Tk() 6 window.geometry('300x200') 7 8 def FolderBrowse(): 9 filedialog.askdirectory(initialdir = "/", title = "Open Folder") 10 11 Button(text='Open a Folder', command=FolderBrowse).pack(anchor=CENTER, expand=True) 12 13 window.mainloop() در کد بالا در خط 3 ابتدا پکیج filedialog را وارد برنامه کرده‌ایم. در خط 11 یک دکمه در وسط فرم قرار داده و در خطوط 9-8 یک تابع تعریف کرده و آن را به خاصیت command دکمه اختصاص می‌دهیم. در مجموع می‌خواهیم، وقتی که بر روی دکمه کلیک شده پنجره‌ای جهت انتخاب پوشه به ما نمایش داده شود. در خط 9 با فراخوانی تابع ()askdirectory، به برنامه گفته‌ایم که قصد ما نمایش پنجره انتخاب پوشه است. حال برنامه را اجرا کنید: مشاهده می‌کنید که با کلیک بر روی دکمه پنجره‌ای باز شده و در داخلان دکمه‌ای به نام Select Folder قرار دارد. “/” = initialdir در خط 9 بدین معناست که وقتی پنجره انتخاب پوشه باز شد، اولین مسیری که نمایش داده شود، همان مسیری باشد که برنامه در داخل آن قرار دارد. برای درک بهتر علامت / را به D: تغییر داده و برنامه را اجرا کنید. مشاهده می‌کنید که اولین مسیری که در داخل پنجره نمایش داده می‌شود همان درایو D است. برای باز کردن فایل هم می‌توان از تابع ()askopenfilename استفاده کرد. خط 9 کد بالا را به صورت زیر تغییر داده: filedialog.askopenfilename(initialdir = "/", title = "Open File", filetypes = (("jpeg files","*.jpg"), ("all files","*.*"))) و برنامه را اجرا کنید: همانطور که مشاهده می‌کنید دکمه Select Folder به Open تغییر نام می‌دهد. به وسیله filetypes هم به برنامه می گوییم که قصد باز کردن چه نوع فایل‌هایی را داریم. نوع فایل‌هایی که در filetypes مشخص می‌کنیم، در داخل لیست کشویی بالای دکمه Open در شکل بالا قابل مشاهده است. استفاده از تابع ()askopenfilename اجازه انتخاب یک فایل را به ما می‌دهد. اگر بخواهیم با چندین فایل را با گرفتن دکمه Ctrl و کلیک بر روی آنها انتخاب کنیم به جای تابع ()askopenfilename کافیست که از تابع ()askopenfilenames استفاده کنیم: برای ذخیره فایل هم می‌توان از تابع ()asksaveasfile استفاده نمود. خط 9 کد ابتدای درس را به صورت زیر تعییر داده: filedialog.asksaveasfile(initialdir = "/", title = "Save As File", filetypes = (("jpeg files","*.jpg"), ("all files","*.*"))) و سپس برنامه را اجرا کنید: حال درایو C را در داخل پنجره انتخاب کرده و سپس در داخل کادر روبروی File Name عبارت Photo.jpg را نوشته و سپس دکمه Save را بزنید: اگر به درایو C مراجعه نمایید، مشاهده می‌کنید که فایل Photo.jpg در داخل آن ذخیره شده است.
  3. Doctor Robot

    Programming-Csharp اموزش 0 تا 100 c#

    رویداد ها (Events) رویدادها، رفتارها یا اتفاقاتی هستند که، در هنگام اجرای برنامه روی می‌دهند. رویدادها معمولاً در برنامه‌های ویژوال مانند ویندوزها یا صفحات وب استفاده می‌شوند. برخی از رویدادها عبارتند از کلیک کردن بر روی ماوس، تایپ یک متن در TextBox، تغییر انتخاب یک آیتم در یک لیست و غیره… . در برنامه‌های کنسول، می‌توانیم به صورت دستی یک رویداد را راه اندازی کنیم. بدین صورت که، یک بلوک کد اضافه می‌کنیم که، وقتی یک حالت خاص اتفاق افتاد، اجرا شود. چندین کنترل کننده رویداد، می‌توانند به یک رویداد متصل شوند. یک کنترل کننده رویداد، متدی است که امضای آن شبیه به امضای delegate مربوط به رویداد است. زیرا هر رویداد به طور ضمنی شامل یک delegate در داخل خود است. زمانی که شما یک کنترل کننده رویداد را به یک رویداد متصل می‌کنید، در واقع شما کنترل کننده یا همان متد را در داخل delegate رویداد قرار می‌دهید. در نتیجه وقتی یک رویداد آزاد می‌شود، همه کنترل کننده‌های رویداد متصل به آن، اجرا می‌شوند. به طور کلی می‌توان گفت که : هر رویداد دارای یک delegate داخلی مربوط به خود است و در نتیجه وقتی که رویداد به وقوع می‌پیوندد، متدهای داخل delegate اجرا می‌شوند. نحوه تعریف یک رویداد به صورت زیر است : accessSpecifier event delegateType EventName; accessSpecifier سطح دسترسی رویداد است و event یک کلمه کلیدی که در تعریف رویداد به کار می‌رود. delegateTypeنوع delegate ی که مورد استفاده قرار گرفته است را مشخص می‌کند. از delegate برای تشخیص امضای کنترل کننده رویدادی که می‌تواند به آن متصل شود استفاده می‌شود. EventName هم نامی است که برای رویداد در نظر می‌گیریم. می‌توان ارتباط بین delegate و event را به صورت زیر خلاصه کرد : یک delegate تعریف می‌کنیم. متدهایی که قرار است هنگام وقوع رویداد اجرا شوند را به delegate اضافه می‌کنیم. یک رویداد (event) ایجاد می‌کنیم. یک متد برای اجرای رویداد تعریف می‌کنیم. آن دسته از متدهای موجود در delegate را که می‌خواهیم هنگام وقوع رویداد اجرا شوند یا نشوند را با استفاده از عملگرهای =+ و =- به رویداد معرفی می‌کنیم. متدی که باعث وقوع رویداد می‌شود را فراخوانی می‌کنیم. برای روشن شدن موارد بالا به مثال زیر توجه کنید : 1 using System; 2 3 public delegate void MessageHandler(); //step 1 4 5 public class Message 6 { 7 public void DisplayMessage() //step 2 8 { 9 Console.WriteLine("Hello World!"); 10 } 11 12 public event MessageHandler ShowMessage; //step 3 13 14 public void ExecuteEvent() //step 4 15 { 16 ShowMessage(); 17 } 18 } 19 20 public class Program 21 { 22 public static void Main() 23 { 24 Message myMessage = new Message(); 25 myMessage.ShowMessage += new MessageHandler(myMessage.DisplayMessage); //step 5 26 27 myMessage.ExecuteEvent(); //step 6 28 } 29 } خروجی کد: Hello World! در کد بالا یک delegate تعریف کرده‌ایم که مقدار برگشتی آن از نوع void بوده و هیچ پارامتری قبول نمی‌کند (خط 3). این امضاء، همان امضای کنترل کننده رویداد می‌باشد. بعد از تعریف delegate یک کلاس (خطوط 18-5) ایجاد می‌کنیم. یک کنترل کننده رویداد یا متد به نام DisplayMessage() که امضای آن شبیه امضای delegate است ایجاد می‌کنیم (خطوط 10-7). این متد در داخل delegate قرار می‌گیرد. در خط 12 یک رویداد و سپس متدی که رویداد را به صورت دستی آزاد می‌کند تعریف می‌کنیم (17-14). رویدادها نمی‌توانند در خارج از کلاسی که در آن قرار دارند آزاد شوند. بنابراین ما از متد ایجاد شده برای اجرای غیر مستقیم آنها استفاده می‌کنیم. در داخل متد Main() یک نمونه جدید از کلاس Message ایجاد می‌کنیم (خط 24). در خط بعد یک کنترل کننده رویداد به رویداد ما متصل می‌شود (خط 25). همانطور که در خط 25 مشاهده می‌کنید، برای اینکه به برنامه بفهمانیم که می‌خواهیم هنگام وقوع رویداد چه متدی از delegate اجرا شود باید به صورت زیر عمل کنیم : EventName += new DelegateType(MethodName); به این نکته توجه کنید که استفاده از عملگر =+ بدین معنی است که، می‌خواهیم یک کنترل کننده رویداد به لیست کنترل کننده‌های رویداد اضافه نماییم. یک نمونه از نماینده (delegate) MessageHandler ایجاد کرده و در داخل آن نام کنترل کننده رویداد را ارسال می‌کنیم (خط 25). وقتی که متد ExecuteEvent() فراخوانی می‌شود، رویداد آزاد و پیغام نمایش داده می‌شود (خط 27). در آینده به مفید بودن رویداد در هنگام کار با فرم‌های ویندوزی و صفحات وب پی خواهید برد.
  4. Doctor Robot

    Programming-Csharp اموزش 0 تا 100 c#

    عملگر (??) null Coalescing عملگر null coalescing، یک عملگر باینری است که، برای تشخیص مقدار دو عملوند به کار می‌رود. کاربرد اصلی این عملگر در قرار دادن یک مقدار nullable در یک مقدار non-nullable با استفاده از یک دستورالعمل ساده‌ است. در زیر نحوه استفاده از عملگر null coalescing نشان داده شده است : var result = operand1 ?? operand2; operand1 و operand2 می‌توانند متغیر، فراخوانی یک متد و یا یک عبارت باشند. اگر operand1 یک متغیر با مقدار تهی باشد و یا فراخوانی یک متد و یا عبارتی باشد که یک مقدار تهی را تولید کند در این صورت عملگر null coalescing به سراغ مقدار عملوند operand2 می‌رود. اگر مقدار این عملوند غیر تهی باشد عملگر null coalescing از آن در نتیجه محاسبه استفاده می‌کند. به مثال زیر توجه کنید : 1 public class Program 2 { 3 public static void Main(string[] args) 4 { 5 int? num1 = null; 6 int? num2 = 100; 7 8 int? num3 = num1 ?? num2; 9 10 Console.WriteLine($"Value is {num3}"); 11 } 12 } خروجی کد: Value is 100 در خط 8 مثال بالا از عملگر null coalescing استفاده کرده‌ایم. از آنجاییکه مقدار اولیه num1 برابر null و مقدار num2 یک مقدار غیر تهی است، در نتیجه مقدار num2 در متغیر num3 قرار می‌گیرد. در مثال زیر هم یک متد را فراخوانی می‌کنیم. البته به طور قطع نمی‌دانیم که آیا با فراخوانی آن یک مقدار تهی برگشت داده می‌شود و یا یک مقدار غیر تهی : 1 using System; 2 3 namespace NullCoalescingOperator 4 { 5 public class Program 6 { 7 public static void Main(string[] args) 8 { 9 Random randomizer = new Random(); 10 11 int? result = GetNullOrIntValue(randomizer.Next(1, 10)) ?? default(int); 12 13 Console.WriteLine($"Result is {result}"); 14 } 15 16 public static int? GetNullOrIntValue(int randomValue) 17 { 18 if (randomValue % 2 == 0) 19 { 20 return null; 21 } 22 23 return 100; 24 } 25 } 26 } خروجی ک: Result is 100 Result is 0 در مثال بالا یک متد به نام ()GetNullOrIntValue تعریف کرده‌ایم که یک مقدار تصادفی به عنوان آرگومان قبول می‌کند. این متد در صورتی که یک مقدار زوج به آن ارسال شود مقدار null و در غیر اینصورت مقدار 100 را بر می‌گرداند. وقتی که در خط 11 این متد را فراخوانی می‌کنیم، یک مقدار تصافی به عنوان آرگومان به آن ارسال می‌شود. عملوند دومی که برای عملگر null coalescing استفاده می‌کنیم کلمه کلیدی default است که برای تشخیص مقدار پیشفرض نوع int یعنی عدد صفر به کار برده شده است. اگر با فراخوانی متد به طور تصادفی یک مقدار زوج به آن ارسال شود، متد مقدار پیشفرض نوع int و در غیر اینصورت یک مقدار غیر تهی (یعنی 100) را بر می‌گرداند.
  5. Doctor Robot

    Programming-Csharp اموزش 0 تا 100 c#

    انواع تهی می‌توانید انواع ساده‌ای مانند int و double ایجاد کنید که مقادیر آنها تهی (null) باشد. مقادیر تهی فقط قابلیت ذخیره سازی انواع مرجع مانند رشته‌ها و سایر اشیاء را دارند. سی شارپ به شما اجازه می‌دهد انواع مقداری را تغییر دهید به طوریکه بتوانند به عنوان انواع تهی به کار روند. می‌توانید از System.Nullable<T> استفاده کنید که در آن T نوعی است که به انواع تهی تبدیل می‌شود. Nullable<int> nullInt = null; Nullable<double> nullDouble = null; همچنین می‌توانید به نوع علامت? را نیز اضافه کنید. int? nullInt = null; double? nullDouble = null; با استفاده از کد زیر می‌توانید تست کنید که آیا متغیر دارای مقدار تهی می‌باشد یا نه؟ if (nullInt == null) { } if (nullDouble.HasValue) { } از آنجاییکه ما آنها را به انواع تهی تبدیل کرده‌ایم نمی‌توان آنها را در یک متغیر از انواع غیر تهی ذخیره نمود. مثلاً کد زیر مجاز نیست : int? nullInt = null; int myNumber = nullInt; برای این کار لازم است که ابتدا آنها را به حالت اصلی برگردانید : int myNumber = (int)nullInt; اگر بخواهید یک نوع تهی با یک مقدار تهی را به حالت اولیه تبدیل کنید یک استثناء روی می‌دهد. وقتی دو نوع تهی (به استثنای نوع بولی ؟) را در یک عملیات در گیر می‌کنیم، اگر یکی از عملوندها تهی باشد نتیجه تهی خواهد بود. نتایج ممکن برای نوع بولی ؟ در جدول زیر آمده است : اگر شما بخواهید از null شدن نتیجه یک عبارت در صورتی که یکی از عملوندهای آن عبارت null باشد جلوگیری کنید، باید از عملگر؟؟ استفاده کنید. int? nullInt = null; int number = nullInt * 5 ?? 10; خط دوم نحوه‌ی استفاده از این عملگر را توضیح می‌دهد. برای نوشتن عبارتی معادل کد بالا از یک عملگر 3 تایی به صورت زیر استفاده می‌کنیم. int number = (nullInt * 5) == null ? (nullInt * 5) : 10; اگر نتیجه عبارت در سمت چپ عملگر ؟؟ برابر null باشد نتیجه عبارت سمت راست عملگر و در غیر این صورت نتیجه مقدار سمت چپ عملگر در متغیر number ذخیره می‌شود
  6. Doctor Robot

    Programming-Csharp اموزش 0 تا 100 c#

    Object Initializer Object Initializer به شما اجازه می‌دهد، خاصیت‌ها را در داخل کلاس مقداردهی کنید. اگر به عنوان مثال چندین خاصیت داشته باشید و نخواهید که یک سازنده را جهت مقداردهی به آنها تعریف کنید، می‌توانید از object initializer استفاده نمایید. به عنوان مثال به کد زیر توجه کنید : using System; public class Sample { public int Property1 { get; set; } public string Property2 { get; set; } public bool Property3 { get; set; } } public class Program { public static void Main() { Sample sampleClass = new Sample(); sampleClass.Property1 = 100; sampleClass.Property2 = "Sample"; sampleClass.Property3 = true; } } همانطور که مشاهده می‌کنید، لازم است که مقادیر را تک به تک به خاصیت‌ها اختصاص دهیم. با استفاده از object initializers می‌توان کد را ساده‌تر کرد : public class Program { public static void Main() { Sample sampleClass = new Sample { Property1 = 100, Property2 = "Hello", Property3 = true }; } } مشاهده می‌کنید که، بعد از ایجاد یک شیء از کلاس به جای پرانتز از آکولاد استفاده کرده و سپس با لیست کردن خاصیت‌ها مقادیری را که لازم داریم، به آنها اختصاص می‌دهیم. به این نکته نیز توجه کنید که خواص به وسیله کاما از هم جدا می‌شوند. هنگام استفاده از object initializers سازنده پیشفرض بدون پارامتر قبل از هر خاصیت مقداردهی شده فراخوانی می‌شود. از آنجاییکه سازنده پیشفرض قبل از اختصاص مقادیر به خاصیت‌ها اجرا می‌شود، می‌توانید مقادیری پیشفرضی به هر یک از خواص اختصاص بدهید، با این کار لازم نیست که حتماً به همه خواص با استفاده از initializer مقدار اختصاص داده شود. اگر یه سازنده غیر پیشفرض (non-default constructor) به کلاس اضافه کنید باز هم باید یک سازنده بدون پارامتر پیشفرض برای قدرت استفاده از object initializers وجود داشته باشد. می‌توان از object initializers تو در تو نیز استفاده نمود. فرض کنید کلاس Sample مان یک خاصیت از نوع Animal که دارای دو خاصیت Name و Age هست را دارا می‌باشد. Sample sampleClass = new Sample { Property1 = 100, Property2 = "Hello", Property3 = true, Property4 = new Animal { Name = "Kitty", Age = 3 }; }; نوع دیگر از مقداردهنده ها collection initializers می‌باشند. collection initializers بسیار شبیه به array initializers می‌باشند با این تفاوت که در کلکسیون‌های عمومی (generic) استفاده می‌شوند. 1 using System; 2 using System.Collections.Generic; 3 4 namespace ObjectInitializer 5 { 6 class Person 7 { 8 public string FirstName { get; set; } 9 10 public Person(string f) 11 { 12 FirstName = f; 13 } 14 } 15 16 class Program 17 { 18 static void Main(string[] args) 19 { 20 List<Person> people = new List<Person> 21 { 22 new Person("John"), 23 new Person("Jenny"), 24 new Person("Joe") 25 }; 26 27 foreach (var person in people) 28 { 29 Console.WriteLine(String.Format("{0}", person.FirstName)); 30 } 31 } 32 } 33 } خروجی کد: John Jenny Joe کد زیر نشان می‌دهد که بدون استفاده از collecition initializers، لازم بود که در خطوط 25-20 آیتم‌ها را به صورت دستی و با استفاده از متد ()Add اضافه کرده یا یک سازنده ایجاد کنیم، که آیتم‌هایی برای کلکسیون قبول کند. List<Person> people = new List<Person>(); people.Add(new Person("John")); people.Add(new Person("Jenny")); people.Add(new Person("Joe"));
  7. Doctor Robot

    Programming-Csharp اموزش 0 تا 100 c#

    کلکسیون عمومی (Generic Collection) می‌توان یک کلکسیون عمومی تعریف کرد که شامل هر نوع داده‌ای باشد. برای ایجاد یک کلکسیون عمومی از کلاس List<T> مربوط به فضای نامی System.Collections.Generics استفاده می‌شود. List<T> می‌تواند مجموعه‌ای از اشیاء نوع T باشد. در نتیجهList<int> مجموعه‌ای از مقادیر صحیح است. کلاس List<T> دارای متدهای AddRange()، Remove()، RemoveAt() و دیگر متدهایی است که در کلاس کلکسیونمان در درس قبلی از آنها استفاده کردیم. using System; using System.Collections.Generic; public class Animal { public string Type; public Animal(string type) { Type = type; } } public class Program { public static void Main() { List<Animal> animals = new List<Animal>(); animals.Add(new Animal("Dog")); animals.Add(new Animal("Cat")); animals.Add(new Animal("Rat")); foreach (Animal animal in animals) { Console.WriteLine(animal.Type); } } } خروجی کد: Dog Cat Rat یکی دیگر از روش‌های مقداردهی به یک کلکسیون استفاده از collection initializers است، که در درس بعد در مورد آن توضیح داده می‌شود. می‌توانید از کلاس Dictionary<TKey, TVal> که در فضای نامی ذکر شده قرار دارد استفاده کنید. Tkey نوع کلید وTval نوع مقدار را مشخص می‌کند. using System; using System.Collections.Generic; public class Animal { public string Type; public Animal(string type) { Type = type; } } public class Program { public static void Main() { Dictionary<string, Animal> animals = new Dictionary<string, Animal>(); animals.Add("Animal1", new Animal("Dog")); animals.Add("Animal2", new Animal("Cat")); animals.Add("Animal3", new Animal("Rat")); foreach (Animal animal in animals.Values) { Console.WriteLine(animal.Type); } } } یک دیکشنری تعریف کرده‌ایم که دارای کلیدهایی از نوع string و مقادیری از نوع کلاس Animal می‌باشد. برای به دست آوردن مقدار آیتم‌های دیکشنری می‌توان از خاصیت Values که شامل همه آیتم‌های دیکشنری است استفاده کرد. خاصیت Keys نیز برای به دست آوردن همه کلیدهای یک دیکشنری به کار می‌رود. کلاس‌هایی را که معرفی کردیم بسیار شبیه به کلاس‌های collection و dictionary هستند که از کلاس‌های CollectionBase و DictionaryBase ارث بری می‌کنند. اما نیازی به ساخت کلاس‌های کالکشن بالا نیست. فقط کافی است که نوع آیتم مورد نظر را به کلاس‌های List<T> وDictionary<TKey,Tvalue> ارسال نمایید. برای اینکه از قابلیت‌های بیشتری بهره مند شوید می‌توانید از collection وdictionary سفارشی استفاده نمایید (یعنی کلاس‌هایی که از CollectionBase و DictionaryBase ارث بری می‌کنند و شما خود متدهای Add() و Remove() آن‌ها را پیاده سازی می‌کنید).
  8. Doctor Robot

    Programming-Csharp اموزش 0 تا 100 c#

    محدودیت نوع (Type Constraints) کد جنریک باید برای هر نوع داده‌ای کار کند. یک عمل محاسباتی مانند عمل جمع که بر روی انواع صحیح انجام می‌شود، نمی‌تواند در صورتی که عملگر + سربارگذاری نشده باشد، بر روی سایر اشیاء عمل کند. در نتیجه شما باید برای یک متد یا کلاس جنریک محدودیت نوع (Type Constraints) در نظر بگیرید که فقط انواع خاصی در این لیست محدودیت قرار بگیرند. public class GenericClass<T> where T: int { //some code } برای ایجاد این محدودیت ابتدا کلمه کلیدی where سپس نام نوع پارامتر، یک کالن (:) و در آخر اگر پارامتر T دارای لیستی از محدودیت‌ها است باید آنها را به وسیله کاما از هم جدا کنیم. کد بالا دارای یک محدودیت است و آن نوع int می‌باشد، بدین معنی که کلاس جنریک ما فقط می‌تواند این نوع را قبول کند. اگر بخواهید چندین محدودیت ایجاد کنید باید به صورت زیر عمل نمایید : public class GenericClass<T> where T: int, string { //some code } پارامتر T در کد بالا فقط نوع int و string را قبول می‌کند. می‌توانید از کلمه کلیدی struct استفاده کنید بدین معنی که، کلاس جنریک فقط انواع مقداری را قبول کند و یا کلمه کلیدی Class را به کار برید که کلاس جنریک فقط انواع مرجع را پذیرا باشد. همچنین می‌توان از کلمه کلیدی interface هم استفاده کرد، که در نتیجه کلاس می‌تواند اشیایی که رابطها را پیاده سازی می‌کنند را، قبول کند. public class GenericClass<T> where T: struct { //some code } public class GenericClass<T> where T: class { //some code } public class GenericClass<T> where T: interface { //some code } همچنین می‌توان نام یک کلاس را به عنوان محدودیت نوع تعیین کرد. بدین معنی که نوع را محدود به آن کلاس و کلاس‌های مشتق شده از آن کند. می‌توان تعیین کرد که کلاس جنریک فقط کلاسهایی که دارای یک سازنده بدون پارامتر هستند را قبول کند. برای ایجاد این محدودیت باید از ()new به صورت زیر استفاده شود : public class GenericClass<T> where T: new() { //some code } در این مورد اگر چندین محدودیت وجود داشته باشد باید ()new را در آخر آنها قرار دهیم. اگر کلاس دارای چندین پارامتر باشد و شما بخواهید برای هر یک از آنها محدودیت‌های مختلفی ایجاد کند می‌توانید دستور where را به صورت زیر اعمال نمایید : public class GenericClass<T1, T2> where T1 : int where T2 : string { //some code } اگر یک کلاس جنریک از یک کلاس دیگر ارث بری کند باید نام آن کلاس را قبل از محدودیت‌ها ذکر نمایید. public class GenericClass<T1, T2> : BaseClass where T1 : int where T2 : string { //some code }
  9. Doctor Robot

    Programming-Csharp اموزش 0 تا 100 c#

    کلاس جنریک تعریف یک کلاس جنریک بسیار شبیه به تعریف یک متد جنریک است. کلاس جنریک دارای یک علامت بزرگتر و کوچک‌تر و یک نوع پارامتر خاص می‌باشد. برنامه زیر مثالی از یک کلاس جنریک می‌باشد : using System; public class GenericClass<T> { private T someField; public GenericClass(T someVariable) { someField = someVariable; } public T SomeProperty { get { return someField; } set { someField = value; } } } public class Program { public static void Main() { GenericClass<double> genericDouble = new GenericClass<double>(30.50); GenericClass<int> genericInt = new GenericClass<int>(10); Console.WriteLine("genericDouble.SomeProperty = {0}", genericDouble.SomeProperty); Console.WriteLine("genericInt.SomeProperty = {0}", genericInt.SomeProperty); genericDouble.SomeProperty = 100.32; genericInt.SompProperty = 50; } } خروجی کد: genericDouble.SomeProperty = 30.50 genericInt.SomeProperty = 10 در مثال بالا یک کلاس جبریک که دارای یک فیلد، یک خاصیت و یک سازنده است را ایجاد می‌کنیم. تمام مکانهایی که ورودی T در آنها قرار دارد بعداً توسط انواعی که مد نظر شما است، جایگزین می‌شوند. وقتی یک نمونه از کلاس جنریک تان ایجاد می‌کنید، یک نوع هم برای آن در نظر بگیرید (<int>). مانند متدهای جنریک می‌توانید چندین نوع پارامتر به کلاسهای جنریک اختصاص دهید. public class GenericClass<T1, T2, T3> { private T1 someField1; private T2 someField2; private T3 someField3; } چون نمی‌دانید T1، T2 و T3 از چه نوعی هستند، نمی‌توانید مانند مثال زیر، از آنها نمونه جدید ایجاد کنید. public GenericClass //Constructor { someField1 = new T1(); someField2 = new T2(); someField3 = new T3(); } کلاسهای غیر جنریک می‌توانند از کلاسهای جنریک ارث بری کنند، اما باید یک نوع برای پارامترکلاس پایه جنریک تعریف کنید. public class MyClass : GenericClass<int> { } یک کلاس جنریک هم می‌تواند از یک کلاس غیر جنریک ارث بری کند.
  10. Doctor Robot

    Programming-Csharp اموزش 0 تا 100 c#

    متدهای جنریک اگر بخواهید چندین متد با عملکرد مشابه ایجاد کنید و فقط تفاوت آنها در نوع داده‌ای باشد که قبول می‌کنند (مثلاً یکی نوع int و دیگری نوع double را قبول کند) می‌توان از متدهای جنریک برای صرفه جویی در کدنویسی استفاده کرد. ساختار عمومی یک متد جنریک به شکل زیر است : returnType methodName<type> (type argument1) { type someVariable; } مشاهده می‌کنید که بعد از نام متد یک نوع در داخل دو علامت بزرگتر و کوچکتر آمده است ( <type> ) که همه انواع در سی شارپ می‌توانند جایگزین آن شوند. برنامه زیر مثالی از نحوه استفاده از متد جنریک می‌باشد : using System; public class Program { public static void Show<X>(X val) { Console.WriteLine(val); } public static void Main() { int intValue = 5; double doubleValue = 10.54; string stringValue = "Hello"; bool boolValue = true; Show(intValue); Show(doubleValue); Show(stringValue); Show(boolValue); } } خروجی کد: 5 10.54 Hello true یک متد جنریک ایجاد کرده‌ایم که هر نوع داده‌ای راقبول کرده و مقادیر آنها را نمایش می‌دهد (خطوط 8-5). سپس داده‌های مختلفی با وظایف یکسان به آن ارسال می‌کنیم. متد نیز نوع X را بسته به نوع داده‌ای که به عنوان آرگومان ارسال شده است تغییر می‌دهد. به عنوان مثال وقتی یک داده از نوع int ارسال می‌کنیم، همه مکانهایی که X در آنها وجود دارد به int تبدیل می‌شوند و متد به صورت زیر در می‌آید : public static void Show (int val) { Console.WriteLine(val); } همچنین هنگام فراخوانی متد جنریک صریحاً می‌توانید نوعی را که به وسیله آن مورد استفاده قرار می‌گیرد ذکر کنید (البته لازم نیست). به عنوان مثال فراخوانی‌های متد بالا را می‌توان به صورت زیر هم نوشت : Show<int>(intValue); Show<double>(doubleValue); Show<string>(stringValue); Show<bool>(boolValue); به یک نکته در مورد استفاده از متدهای جنریک توجه کنید و آن این است که، قبل از دانت نت 4.5، انجام محاسبات به وسیله متدهای جنریک امکان پذیر نبود. یعنی شما نمی توانستید که دو عدد را با هم جمع کنید: public static void Show<X>(X val1, X val2) { Console.WriteLine(val1 + val2); } ولی در نسخه 4.5 دات نت این مشکل با استفاده از کلمه کلیدی dynamic به صورت زیر قابل حل است : Console.WriteLine((dynamic)val1 + (dynamic)val2); شما می‌توانید چندین نوع خاص را برای متد جنریک ارسال کنید، برای این کار هر نوع را به وسیله کاما از دیگری جدا کنید. public static void Show<X, Y>(X val1, Y val2) { Console.WriteLine(val1); Console.WriteLine(val2); } به مثال زیر که در آن دو مقدار مختلف به متد ارسال شده است توجه کنید : Show(5, true); // OR Show<int, bool>(5, true); مشاهده می‌کنید که X با نوع int و Y با نوع bool جایگزین می‌شود. این نکته را نیز یادآور شویم که شما می‌توانید دو آرگومان هم نوع را هم به متد ارسال کنید : Show(5, 10); // OR Show<int, int>(5, true);
  11. Doctor Robot

    Programming-Csharp اموزش 0 تا 100 c#

    جنریک ها (Generics) جنریک ها کلاس‌ها، متدها یا رابط‌هایی هستند که بسته به نوع داده‌ای که به آنها اختصاص داده می‌شود رفتارشان را سازگار می‌کنند. به عنوان مثال می‌توان یک متد جنریک تعریف کرد که هر نوع داده‌ای را قبول کند. همچنین می‌توان یک متد ایجاد کرد که بسته به نوع دریافتی، مقادیری از انواع داده‌ای مانند int، double یا string را نشان دهد. اگر از جنریک ها استفاده نکنید باید چند متد و یا حتی چندین متد سربارگذاری شده برای نمایش هر نوع ممکن ایجاد کنید. public void Show(int number) { Console.WriteLine(number); } public void Show(double number) { Console.WriteLine(number); } public void Show(string message) { Console.WriteLine(message); } با استفاده از جنریک ها می‌توان متد جنریکی ایجاد کرد که هر نوع داده‌ای را قبول کند. public void Show<E>(E item) { Console.WriteLine(item); } متدهای جنریک را در درسهای آینده توضیح خواهیم داد. حتماً این سؤال را از خودتان می‌پرسید که چرا نباید از نوع آبجکت که هر نوع داده‌ای را قبول می‌کند استفاده کنیم؟ در آینده مشاهده می‌کنید که با استفاده از جنریک ها نیاز به عمل cast (تبدیل صریح) ندارید. درباره جنریک ها در درسهای بعد مطالب بیشتری توضیح می‌دهیم.
  12. Doctor Robot

    Programming-Csharp اموزش 0 تا 100 c#

    پیمایشگر (Iterator) Iterator بلوک کدی است که، شامل همه مقادیری است که در یک حلقه foreach مورد استفاده قرار می‌گیرد. یک کلاس که نماینده یک کلکسیون است می‌تواند رابط System.Collections.IEnumerable را پیاده سازی کند. این رابط نیاز به پیاده سازی متد ()GetEnumerator دارد که یک رابط IEnumerator را بر می‌گرداند. رابط IEnumerator دارای خاصیت Current می‌باشد که مقدار جاری برگشت داده شده بوسیله iterator را در بر دارد. این رابط (IEnumerator) همچنین دارای متد ()MoveNext است که خاصیت Current را به سوی آیتم بعدی حرکت می دهد و در صورت عدم وجود آیتم مقدار false را بر می‌گرداند. متد ()Reset حلقه پیمایش را به اولین آیتم بر می‌گرداند. رابط IEnumerator توسط کلکسیون‌های مختلف دات نت پیاده سازی می‌شود که یکی از این کلکسیون‌ها آرایه‌های می‌باشند. پس این سؤال پیش می‌آید که چگونه با استفاده از حلقه foreach می‌توان به اجزای این کلکسیون‌ها دسترسی پیدا کرد؟ فرض کنید کدی شبیه به کد زیر داریم که همه عناصر یک آرایه را با استفاده از حلقه foreach می‌خواند. int[] numbers = { 1, 2, 3, 4, 5 }; foreach(int n in numbers) { Console.WriteLine(n); } برای درک بهتر کاربرد تکرارکننده‌ها (iterators)، اجازه دهید که حلقه foreach کد بالا را به فراخوانی متد ()GetEnumerator آرایه ترجمه کنیم : int[] numbers = { 1, 2, 3, 4, 5 }; IEnumerator iterator = numbers.GetEnumerator(); while (iterator.MoveNext()) { Console.WriteLine(iterator.Current); } همانطور که مشاهده می‌کنید ما ابتدا یک پیمایشگر آرایه را با استفاده از متد ()GetEnumerator که یک رابط IEnumerator را بر می‌گرداند به دست می‌آوریم. سپس از این پیمایشگر در حلقه while استفاده کرده و متد ()MoveNext را فراخوانی می‌کنیم. متد ()MoveNext اولین عنصر یک کلکسیون مانند آرایه را بر می‌گرداند و اگر عملیات به دست آوردن اولین عنصر موفقیت آمیز باشد مقدار true را بر می‌گرداند. در فراخوانی بعدی دومین عنصر آرایه را بر می‌گرداند و این کار را تا آخرین عنصر آرایه انجام می‌دهد و وقتی که به پایان عناصر رسید مقدار false را برگشت می‌دهد. مقدار برگشت داده شده یک عنصر به وسیله خاصیت IEnumerator.Current قابل دسترسی است. برای استفاده از iterator نیاز به دستور yield return داریم. این دستور (yield) با دستور return متفاوت است. یکی از تفاوت‌های مشهود این دو، استفاده از کلمه کلیدی yield قبل از کلمه کلیدی return می‌باشد. yield یک عنصر مجموعه را برمی گرداند و موقعیت مکان نما را به عنصر بعدی هدایت می‌کند. به کد زیر توجه کنید : public static IEnumerable GetMessages() { yield return "Message 1"; yield return "Message 2"; yield return "Message 3"; } public static void Main() { foreach (string message in GetMessages()) { Console.WriteLine(message); } } خروجی کد: Message 1 Message 2 Message 3 متد ()GetMessages یک شئ IEnumerable را بر می‌گرداند که، شامل تعریفی برای یک متد ()GetEnumerator می‌باشد. مقدار جلوی اولین دستور yield return در متغیر message دستور foreach قرار می‌گیرد و چاپ می‌شود. در فراخوانی بعدی متد ()GetMessages در حلقه foreach مقدار جلوی دومین دستور yield return چاپ می‌شود و این کار تا آخرین دستور yield return ادامه می‌یابد. برای توقف مقادیر برگشتی از متد می‌توان از دستور yield break به صورت زیر استفاده کرد : public static IEnumerable GetMessages() { yield return "Message 1"; yield return "Message 2"; yield break; yield return "Message 3"; } حال که با نحوه عملکرد پیمایشگرها آشنا شدید، شما را با نحوه ایجاد یک پیمایشگر سفارشی آشنا می‌کنیم. اجازه دهید با ذکر یک مثال نحوه استفاده از پیمایشگر را به وسیله ایجاد یک کلاس جدید که شامل یک فیلد ArrayList است توضیح دهیم. می‌خواهیم یک پیمایشگر ایجاد کنیم که با استفاده از حلقه foreach مقادیر ArrayList را به دست آورد. 1 using System.Collections; 2 using System; 3 4 public class Names : IEnumerable 5 { 6 private ArrayList innerList; 7 8 public Names(params object[] names) 9 { 10 innerList = new ArrayList(); 11 12 foreach (object n in names) 13 { 14 innerList.Add(n); 15 } 16 } 17 18 public IEnumerator GetEnumerator() 19 { 20 foreach (object n in innerList) 21 { 22 yield return n.ToString(); 23 } 24 } 25 } 26 27 public class Program 28 { 29 public static void Main() 30 { 31 Names nameList = new Names("John", "Mark", "Lawrence", "Michael", "Steven"); 32 33 foreach (string name in nameList) 34 { 35 Console.WriteLine(name); 36 } 37 } 38 } خروجی کد: John Mark Lawrence Michael Steven ابتدا یک کلاس مجموعه‌ای به نام Names که شامل لیستی از نام‌ها می‌باشد را ایجاد می‌کنیم (خطوط 25-4). همانطور که در تعریف کلاس در خط 4 مشاهده می‌کنید، ما کلاس CollectionBase را پیاده سازی نکرده‌ایم. چون که کلاس CollectionBase رابط IEnumerable را پیاده سازی می‌کند و در نتیجه دارای یک پیاده سازی از متد ()GetEnumerator این رابط نیز است. ما یک کلاس مجموعه‌ای را از صفر ایجاد و یک پیمایشگر سفارشی را تعریف کرده‌ایم. از آنجاییکه کلاس ما رابط IEnumerable را پیاده سازی کرده است پس لازم است که متد ()GetEnumerator از این رابط را هم پیاده سازی کند. متد ()GetEnumerator یک شمارنده است که کلکسیون‌ها را شمارش می‌کند. کلکسیون به مجموعه‌ای از عناصر هم نوع که الزاماً در حافظه پشت سر هم نیستند گفته می‌شود. در خطوط 24-18 پیمایشگر سفارشی را تعریف کرده‌ایم. در داخل آن به پیمایش هر یک از مقادیر فیلد innerList می‌پردازیم. هر مقدار به رشته تبدیل و و سپس با استفاده از دستور yield به متد فراخوان ارسال می‌شود. خطوط 36 – 33 پیمایشگر ما را در عمل نمایش می‌دهد. از آنجاییکه دستور yield در پیمایشگرمان هر مقدار را به نوع رشته تبدیل می‌کند پس به راحتی می‌توانیم از نوع string در حلقه foreach استفاده کنیم (خط 33). وقتی که یک مقدار به وسیله پیمایشگر از طریق حلقه foreach واقع در متد ()Main برگدانده می‌شود، حلقه foreach به آیتم بعدی رفته و دستور yield مقدار پیمایش شده از innerList را بر می‌گرداند. بدون پیمایشگر ما قادر به استفاده از حلقه foreach در کلاسمان نیستیم. ایجاد پیمایشگر سفارشی به ما این قدرت را می‌دهد که کنترل بیشتری بر رفتار حلقه foreach هنگام کار با کلاس داشته باشیم. به عنوان مثال می‌توانیم پیمایشگر را به این صورت اصلاح کنیم که فقط نام‌هایی که با حرف M شروع می‌شوند را برگرداند : public IEnumerator GetEnumerator() { foreach (object n in innerList) { if (n.ToString().StartsWith("M")) yield return n.ToString(); } } همانطور که در کد بالا مشاهده می‌کنید برای تشخیص اینکه چه نامی با حرف M شروع شده است از متد ()StartsWith مربوط به کلاس System.String استفاده کرده‌ایم. اگر نام با حرف M شروع شده باشد، دستور yield آن را بر می‌گرداند، در غیر اینصورت، از آن رد شده و به نام بعدی در innerList را مورد بررسی قرار می‌دهد. با دستکاری متد ()GetEnumerator، هنگام استفاده از حلقه foreach در یک نمونه از کلاس Names، می‌توانیم فقط نام‌هایی را که با حرف M شروع می‌شوند را به دست آوریم. اگر چه می‌توانید از تکنیک بالا استفاده کرده و متد ()GetEnumerator تغییر دهید ولی بهتر است از یک متد جدا برای به دست آوردن نام‌هایی که با یک حرف خاص شروع می‌شوند استفاده کنید : public IEnumerable GetNamesStartingWith(string letter) { foreach (object n in innerList) { if (n.ToString().StartsWith(letter)) yield return n.ToString(); } } پیمایشگر بالا نسبت به پیمایشگر قبلی منعطف‌تر بوده و شما می‌توانید با استفاده از آن نام‌هایی که با یک حرف یا زیررشته خاص شروع شده‌اند را پیدا کنید. به این نکته توجه کنید که در پیمایشگر بالا از IEnumerable به جای IEnumerator استفاده کرده‌ایم. IEnumerable دارای متد ()GetEnumerator است. هنگام فراخوانی این پیمایشگر لازم است که حلقه foreach خطوط 36-33 را به صورت زیر تغییر دهید : foreach (string name in nameList.GetNamesStartingWith("M")) { Console.WriteLine(name); }
  13. Doctor Robot

    Programming-Csharp اموزش 0 تا 100 c#

    رابط IEnumerable یک کلاس قابل شمارش (enumerable) کلاسی است که رابط IEnumerable را پیاده سازی کند. رابط IEnumerable فقط یک عضو دارد و آن عضو هم متد ()GetEnumerator می‌باشد و پارامتر برگشتی این متد از نوع همان رابط IEnumberator است. این رابط در واقع کلاس ما را قابل پیمایش می‌کند تا بتوانیم حلقه foreach را در مورد کلاسمان بکار ببریم. فرم کلی بصورت زیر است : using System.Collections; class MyClass : IEnumerable { public IEnumerator GetEnumerator { ... } ... } اکنون یک مثال را با هم مرور می‌کنیم. فرض کنید یک کلاس به نام ColorEnumerator که رابط IEnumerator را پیاده سازی می‌کند. این کلاس یک رشته از رنگها را در بر می‌گیرد، و چون رابط IEnumerator را پیاده سازی می‌کند، پس قابل پیمایش می‌شود : using System; using System.Collections; class ColorEnumerator : IEnumerator { string[] Colors; int Position = -1; public ColorEnumerator(string[] theColors) // Constructor { Colors = new string[theColors.Length]; for (int i = 0; i < theColors.Length; i++) Colors[i] = theColors[i]; } public object Current // Implement Current. { get { return Colors[Position]; } } public bool MoveNext() // Implement MoveNext. { if (Position < Colors.Length - 1) { Position++; return true; } else return false; } public void Reset() // Implement Reset. { Position = -1; } } اکنون ما کلاسی دیگر ایجاد می‌کنیم که رابط IEnumerable را پیاده سازی می‌کند، این کلاس در متد ()GetEnumerator پارامتری از نوع کلاس بالا برمی گرداند مطابق شکل زیر : class MyColors : IEnumerable { string[] Colors = { "Red", "Yellow", "Blue" }; public IEnumerator GetEnumerator() { return new ColorEnumerator(Colors); } } حال در برنامه براحتی می‌توانیم از حلقه foreach برای پیمایش اعضای آن استفاده کنیم. به کد زیر توجه کنید : class Program { static void Main() { MyColors MC = new MyColors(); foreach (string color in MC) Console.WriteLine(color); } } خروجی کد: Red Yellow Blue
  14. Doctor Robot

    Programming-Csharp اموزش 0 تا 100 c#

    رابط IEnumerator یک شمارنده (enumerator) رابط IEnumerator را پیاده سازی می‌کند که دارای دو متد ()MoveNext() ،Reset و یک خاصیت به نام Current می‌باشد. خاصیت Current عنصر جاری یک مجموعه را بر می‌گرداند. این خاصیت یک خاصیت فقط خواندنی (read-only) است و چیزی که برمی گرداند از نوع object می‌باشد. متد ()MoveNext متدی است که، مکان شمارنده را از یک آیتم در مجموعه به آیتمی دیگر منتقل می‌کند. این متد یک مقدار بولی را بر می‌گرداند که نشان می‌دهد که آیا مکان دیگری برای خواندن در دسترس است یا به انتهای مجموعه رسیده است. اگر مکان جدیدی وجود داشته باشد مقدار true و در غیر اینصورت مقدار false را بر می‌گرداند. مکان اولیه شمارنده قبل از اولین آیتم مجموعه است، بنابراین ()MoveNext باید قبل از اولین دسترسی خاصیت Current فراخوانی شود. متد ()Reset متدی برای برگرداندن شمارنده به موقعیت اولیه خود قبل از جابجایی است. به تعبیری دیگر، موقعیت اولیه مجموعه را برمی گرداند. با در اختیار داشتن یک شمارنده (enumerator) شما قادر خواهید بود که حلقه foreach را شبیه سازی کرده و عناصر یک مجموعه را با استفاده ازمتد ()MoveNext و خاصیت Current پیمایش کنید. برای درک بهتر عملکرد دو متد و خاصیت مذکور به شکل و کد زیر توجه کنید : int[] numbers = { 10, 11, 12, 13 }; IEnumerator IEnumerator1 = numbers.GetEnumerator(); IEnumerator1.MoveNext(); int i = (int)IEnumerator1.Current; Console.WriteLine(i.ToString()); خروجی کد: 10 همانطور که در کد بالا مشاهده می‌کنید متد ()GetEnumerator آرایه numbers را به نوع شمارش پذیر تبدیل می‌کند، سپس با فراخوانی متد ()MoveNext عدد 10 که اولین عضو آرایه است به عنوان عنصر جاری (Current) بر گردانده می‌شود. حال فرض کنید که شما می‌خواهید عدد 12 را چاپ کنید، برای این کار باید متد ()MoveNext را سه با فراخوانی کنید : int[] numbers = { 10, 11, 12, 13 }; IEnumerator IEnumerator1 = numbers.GetEnumerator(); IEnumerator1.MoveNext(); IEnumerator1.MoveNext(); IEnumerator1.MoveNext(); int i = (int)IEnumerator1.Current; Console.WriteLine(i.ToString()); خروجی کد: 12 آرایه‌ها از انواع قابل شمارش (enumerable) هستند، بنابراین کد زیر روش دستی کاری است که حلقه foreach به صورت خودکار انجام می‌دهد. در حقیقت کامپایلر #C کدی شبیه به کد زیر را در هنگام نوشتن دستور foreach تولید می‌کند: using System; using System.Collections; public class Program { public static void Main() { int[] numbers = { 10, 11, 12, 13 }; IEnumerator IEnumerator1 = numbers.GetEnumerator(); while (IEnumerator1.MoveNext()) { int i = (int)IEnumerator1.Current; Console.WriteLine("{0}", i); } } } خروجی کد: 10 11 12 13
  15. Doctor Robot

    Programming-Csharp اموزش 0 تا 100 c#

    رابط های IEnumerator و IEnumerable تمامی کلاسهایی که به نحوی شامل یک Collection هستند، این دو رابط رو پیاده سازی می‌کنند. وجود IEnumerable که توسط کلاسها پیاده سازی می‌شود به کلاس این امکان را می‌دهد که بصورت ضمنی و توکار بشود شیء را پیمایش کرد. دقیقاً به همین دلیل می‌توان با استفاده از حلقه foreach یک آرایه را پیمایش کرد، چون که رابط IEnumerable توسط کلاس System.Array پیاده سازی می‌شود. رابط IEnumerator در سطح پایین‌تری از یک IEnumerable قرار دارد. با استفاده از این رابط می‌توان در هرجای بدنه متد اشیایی رو برگشت دهیم بدون اینکه مجبور باشیم ابتدا نتایج را مثلاً در یک آرایه بریزیم و بعد آن آرایه رو برگشت دهیم.
  16. Doctor Robot

    Programming-Csharp اموزش 0 تا 100 c#

    استفاده از حلقه foreach وقتی که از حلقه foreach در یک آرایه استفاده می‌کنید، این حلقه تک تک اعضای آرایه را به شما ارائه داده و اجازه می‌دهد که مقادیر آنها را مشاهده کنید. به عنوان مثال در زیر یک آرایه با چهار عنصر تعریف شده است و می‌خواهیم با استفاده از حلقه foreach مقادیر عناصر آن را چاپ کنیم : int[] number = { 10, 11, 12, 13 }; foreach (int item in number) Console.WriteLine("Item value: {0}", item); خروجی کد: Item value: 10 Item value: 11 Item value: 12 Item value: 13 اما چرا از این حلقه برای آرایه‌ها استفاده می‌کنیم؟ چون آرایه به محض درخواست، یک شیء به نام enumerator (شمارنده) تولید می‌کنند. این شیء می‌تواند عناصر آرایه را یک به یک و به ترتیب برگرداند. Enumerator ترتیب عناصر آرایه را می‌داند و بعد از برگرداندن اولین عنصر موقعیت خود را حفظ کرده و در درخواست بعدی عنصر بعدی آرایه را بر می‌گرداند. برای انواعی که دارای شئ شمارنده (enumerator) هستند یک راه برای به دست آوردن این شئ وجود دارد و آن استفاده از متد ()GetEnumerator است. به انواعی که این متد را پیاده سازی می‌کنند نوع شمارش پذیر یا enumerable می گویند. آرایه یک نوع شمارش پذیر است. از حلقه foreach برای کار با انواع شمارش پذیر (enumerable) استفاده می‌شود. وقتی که یک نوع شمارش پذیر به این حلقه می‌دهیم تا عناصر آن را شمارش کند، مراحل زیر طی می‌شود : ابتدا شئ enumerator را با فراخوانی متد ()GetEnumerator به دست می‌آورد. هر آیتم را از enumerator درخواست کرده و آن را برای شما قابل دسترس می‌کند (نه قابل تغییر).
  17. Doctor Robot

    Programming-Csharp اموزش 0 تا 100 c#

    انواع Enumerator و Enumerable در درس‌های قبلی دیدید که چگونه با استفاده از حلقه foreach عناصر یک آرایه را پیمایش می‌کردیم. در این درس می‌خواهیم کمی دقیقتر به قضیه آرایه‌ها نگاه کنیم و ببینیم که چرا از آن‌ها می‌توانند توسط این حلقه مورد پردازش قرار گیرند. همچنین یاد می‌گیرید که چطور از این قابلیت در کلاس‌هایی که خودتان تعریف کرده‌اید استفاده کنید.
  18. Doctor Robot

    Programming-Csharp اموزش 0 تا 100 c#

    Hashtable از Hashtable زمانی استفاده می شود که بخواهید اطلاعات را بر اساس کلید/ مقدار ذخیره کنید. به عنوان مثال نام دانش آموز و نمره او در امتحان.Hashtable به شما اجازه تلفیق متن و عدد را می دهد. یک پروژه جدید ایجاد کنید. با زدن دکمه F7 به محیط کدنویسی رفته و در بالای کدها و در قسمت تعریف فضای نام، فضای نام زیر را وارد کنید : using System.Collections; Hashtable در این فضای نام قرار دارد. کد زیر را هم در داخل متد Main وارد کنید. Hashtable students = new Hashtable(); کد بالا یک شئ به نام students ایجاد می کند. دو راه برای اضافه کردن داده ها به Hashtable وجود دارد. این دو روش در زیر نشان داده شده اند : students["Jenny"] = 87; students["Peter"] = "No Score"; students["Mary Jane"] = 64; students["Azhar"] = 79; یا students.Add("Jenny", 87); students.Add("Peter", "No Score"); students.Add("Mary Jane", 64); students.Add("Azhar", 79); در روش اول از براکت استفاده شده است : students["Jenny"] = 87; در داخل براکت ها کلید را تایپ می کنید. که در این مورد خاص “jenny” می باشد. سپس بعد از علامت مساوی مقدار کلید را می نویسید. به این نکته توجه کنید که سه ورودی بالا دارای مقدار عددی بوده به جز Peter که دارای مقدار متنی می باشد. در روش دوم مقادیر یا استفاده از متد Add در Hashtable ذخیره می شوند: students.Add("Jenny", 87); در بین دو پرانتز ()Add، ابتدا نام کلید سپس کاما و بعد از کاما مقدار کلید را می نویسید. تفاوتی بین این دو وجود دارد. اگر از متد ()Add استفاده کنید نمی توانید از کلیدهای مشابه استفاده کنید. اما هنگام استفاده از براکت می شود، پیغام خطا می دهد : students.Add("Jenny", 87); students.Add("Jenny", 35); پیغام خطا نمی دهد : students["Jenny"] = 87; students["Jenny"] = 35; حال در زیر شئ ایجاد شده کدهای زیر را هم اضافه کنید: Hashtable students = new Hashtable(); students["Jenny"] = 87; students["Peter"] = "No Score"; students["Mary Jane"] = 64; students["Azhar"] = 79; foreach (DictionaryEntry child in students) { Console.WriteLine("student: " + child.Key + " , Score: " + child.Value); } قبل از اجرای کد به حلقه foreach توجه کنید. در داخل پرانتزها از دستور زیر استفاده کرده ایم : DictionaryEntry child کد بالا یک متغیر به نام child را که نوع آن یک DictionaryEntry می باشد ایجاد می کند. سی شارپ با استفاده از یک شی از این نوع در هنگام کار با Hashtable، مقادیر و کلید ها را برگشت می دهد. در مثال فوق مقادیر و کلید ها را در داخل کنترل listbox نشان می دهیم. "student: " + child.Key + " , Score: " + child.Value بعد از نوشتن نام متغیرمانIntelliSense ، (child) ظاهر می شود. Key خاصیتی است که نام کلید و Value خاصیتی است که مقدار کلید را برگشت می دهد. نتیجه اجرای برنامه به صورت زیر است : student: Mary Jane , Score:64 student: Jenny , Score:87 student: Peter , Score: "No Score" student: Azhar , Score: 79 همانند یک لیست (List) می تواندی با استفاده از متدهای Add و Remove آتم هایی به Hashtable اضافه و یا از آن کم کنید.مانند زیر : students.Remove("Peter"); همانطور که می بینید با استفاده از نام کلید، نه مقدار ، یک آیتم را می توان حذف نمود.
  19. Doctor Robot

    Programming-Csharp اموزش 0 تا 100 c#

    ساخت دیکشنری می توان یک کلاس ایجاد کرد که از کلاس DictionaryBase مشتق شود. با این روش شما می توانید به هر عنصر با استفاده از یک کلید (key) (که معمولا از نوع رشته است) دسترسی یابید. این کلیدها دارای یک مقدار (value) وابسته به خود هستند. برای فراخوانی هر یک از آیتم های دیکشنری از کلید آن استفاده می کنیم نه از اندیس آن. به کد زیر توجه کنید : using System.Collections; public class Animal { public string Name { get; set; } public int Age { get; set; } public double Height { get; set; } public Animal(string name, int age, double height) { Name = name; Age = age; Height = height; } } public class Animals : DictionaryBase { public void Add(string key, Animal newAnimal) { Dictionary.Add(key, newAnimal); } public void Remove(string key) { Dictionary.Remove(key); } public Animal this[string key] { get { return (Animal)Dictionary[key]; } set { Dictionary[key] = value; } } } یک کلاس به نام Animal تعریف کرده ایم که قرار است در کلاس دیکشنری مورد استفاده قرار بگیرد(خطوط 15-3). سپس یک کلاس به نام Animals ایجاد می کنیم (نام یکی از کلاس ها Animal و دیگری Animals است)که از کلاس DictionaryBase ارث بری می کند. حال می توان متدهایی برای حذف و اضافه ورودی های دیکشنری تعریف کرد. متد ()Add به یک کلید از نوع رشته و یک شی Animal که می خواهیم به دیکشنری اضافه کنیم احتیاج دارد. از خاصیت Dictionary کلاس DictionaryBase برای اضافه کردن یک ورودی به دیکشنری استفاده می کنیم. متد ()Remove فقط به کلید شی ایی که می خواهیم حذف کنیم نیاز دارد. در این متد هم از خاصیت Dictionary برای حذف آیتم ها استفاده می کنیم. ما یک ایندکسر تعریف کرده ایم که به جای یک مقدار int ، یک کلید از نوع رشته قبول می کند. اجازه بدهید برای نشان دان توانایی های کلاس دیکشنری مان یک کلاس ایجاد کنیم. using System; public class Program { public static void Main() { Animals animalDictionary = new Animals(); animalDictionary.Add("Animal1", new Animal("John", 10, 100)); animalDictionary.Add("Animal2", new Animal("Sussy", 5, 10)); animalDictionary.Add("Animal3", new Animal("Frank", 3, 5)); animalDictionary.Add("Animal4", new Animal("Mark", 7, 15)); Console.WriteLine("Accessing entries by their keys"); for (int i = 0; i < animalDictionary.Count; i++) { Console.WriteLine(animalDictionary["Animal" + (i + 1)].Name); } animalDictionary.Remove("Animal3"); Console.WriteLine("nFrank was removed from the dictionary."); Console.WriteLine("nIterating using foreach loop."); foreach (DictionaryEntry animal in animalDictionary) { Console.WriteLine((animal.Value as Animal).Name); } } } خروجی کد: Accessing entries by their keys John Sussy Frank Mark Frank was removed from the dictionary. Iterating using foreach loop. John Mark Sussy یک نمونه جدید از کلاس دیکشنری Animals ایجاد می کنیم. سپس چند نمونه از کلاس Animal و کلیدهای مربوط به آنها را به آن اضافه می کنیم. همانطور که در مثال بالا مشاهده می کنید می توانیم با استفاده از حلقه for به هر یک از ورودی با استفاده از کلیدشان که حکم اندیس دارد دست یابیم. سپس با استفاده از متد ()Remove سومین ورودی دیکشنری را با استفاده از کلیدش حذف کرده ایم. و بعد مقادیر را با استفاده از یک حلقه foreach می خوانیم و چاپ می کنیم. شما باید به یک تفاوت توجه کنید. ما از DictionaryEntry به عنوان نوع استفاده کرده ایم چون هر آیتم در کلاس dictionary یک نوع دارد. شی واقعی در داخل خاصیت DictionaryEntry ، Value قرار دارد. این مقدار را با استفاده از عمل cast به نوع مناسب تبدیل می کنیم.
  20. Doctor Robot

    Programming-Csharp اموزش 0 تا 100 c#

    ایجاد یک کلکسیون سی شارپ به شما توانایی ایجاد کلکسیون ی از کلاس ها را می دهد. به عنوان مثال می توان کلاسی ایجاد کرد که شامل چندین نمونه از کلاس های دیگر باشد. این کلاس خصوصیاتی مانند حذف و اضافه نمونه ها از کلکسیون را دارا می باشد. به مثال زیر توجه کنید : using System.Collections; public class Animal { public string Name { get; set; } public int Age { get; set; } public double Height { get; set; } public Animal(string name, int age, double height) { Name = name; Age = age; Height = height; } } public class Animals : CollectionBase { public void Add(Animal newAnimal) { List.Add(newAnimal); } public void Remove(Animal oldAnimal) { List.Remove(oldAnimal); } } در مثال بالا دو کلاس تعریف شده است. اولین کلاس، کلاس Animal است که یک عنصر از کلکسیون کلاسمان است. دومین کلاس، کلکسیون کلاسمان است (Animals) که شامل مجموعه ای از اشیاء کلاس Animal می باشد. برای استفاده بهتر از کاربرد کلکسیون ها، کلاسمان از کلاس CollectionBase ارث بری می کند. به این نکته توجه کنید که فضای نام System.Collections را قسمت تعریف فضاهای نامی وارد کنید. کلاس CollectionBase دارای متدهایی مانند ()Add و ()Remove و خاصیت List که مجموعه ای از اشیاء را در خود جای می دهد، می باشد. برای حذف یا اضافه کردن اشیاء به سادگی می توان از خاصیت List و متد مربوطه استفاده نمود. متدهای خاصیت List یک شیء قبول می کنند نه یک کلاس.بنابراین وقتی که یک ایندکسر تعریف می کنیم لازم است که ابتدا با استفاده از عمل cast نتیجه را تبدیل و سپس آن را به کاربر برگشت دهیم. public Animal this[int index] { get { return (Animal)List[index]; } set { List[index] = value; } } با استفاده از کد بالا می توانیم به هر یک از اشیاء کلکسیون بوسیله اندیس مکانشان دسترسی یابیم. از آنجاییکه خاصیت List، شی قبول می کند لازم است که با استفاده از عمل cast آنها را به اشیاء Animal تبدیل کنیم. به برنامه زیر توجه کنید : public class Program { public static void Main() { Animals animalCollection = new Animals(); animalCollection.Add(new Animal("Jack", 10, 100)); animalCollection.Add(new Animal("Sussy", 5, 10)); animalCollection.Add(new Animal("Frank", 3, 5)); for (int i = 0; i < animalCollection.Count; i++) { Console.WriteLine("Animal {0}", i + 1); Console.WriteLine("Name: {0}", animalCollection[i].Name); Console.WriteLine("Age: {0}", animalCollection[i].Age); Console.WriteLine("Height: {0}n", animalCollection[i].Height); } } } خروجی کد: Animal 1 Name: Jack Age: 10 Height: 100 Animal 2 Name: Sussy Age: 5 Height: 10 Animal 3 Name: Frank Age: 3 Height: 5 در برنامه بالا یک نمونه از کلاس Animals (animalCollection) و سپس سه نمونه به آن با استفاده از متد ()Add اضافه کرده ایم.سپس با گردش در میان عناصر با استفاده از یک حلقه نشان داده ایم که می توان با استفاده از اندیس به آنها دست یافت. این کار را با استفاده از یک حلقه foreach هم می توان انجام داد: foreach (Animal animal in animalCollection) { } در درس آینده با generic ها آشنا می شوید، که راهی آسان برای ایجاد کلکسیونی از هر نوع ، بدون ایجاد کلاسی که از کلاس پایه CollectionBase ارث بری کند، می باشد.
  21. Doctor Robot

    Programming-Csharp اموزش 0 تا 100 c#

    مرتب سازی مقادیر ArrayList با استفاده از متد Sort می‌توان مقادیر یک آرایه را مرتب نمود. اعداد از بزرگ به کوچک و رشته بر اساس حروف الفبا مرتب می‌شوند. اگر از این متد استفاده کنید همه اجزا با هم مقایسه می‌شوند. به عنوان مثال نمی‌توان یک رشته و یک عدد از نوع int را در داخل ArrayList قرار داد و آنها را با متد ()Sort مرتب نمود. در درس آینده یاد خواهید گرفت که چگونه از یک مقایسه گر سفارشی برای مرتب کردن عناصر استفاده نمود.
  22. Doctor Robot

    Programming-Csharp اموزش 0 تا 100 c#

    جستجوی مقادیر با استفاده از متد ()Contains می‌توان چک کرد که آیا یک مقدار خاص در داخل آرایه وجود دارد یا خیر. این متد یک آرگومان از نوع شیء را قبول کرده و اگر یک مقدار را در داخل لیست عناصر پیدا کند true را بر می‌گرداند، از متدهای ()IndexOf و ()LastIndexOf برای تشخیص اندیس یک مقدار خاص استفاده می‌شود. متد ()IndexOf اندیس اولین محل وقوع یک مقدار خاص را بر می‌گرداند. متد ()LastIndexOf اندیس آخرین محل وقوع یک مقدار خاص را بر می‌گرداند. هر دو متد، در صورتیکه مقدار مورد نظر را پیدا نکنند مقدار 1- را بر می‌گردانند. متد ()BinarySearch هم می‌توان برای جستجوی یک مقدار استفاده نمود. البته این متد برای جستجو یک عنصر در داخل تعداد زیادی از عناصر مناسب است.
  23. Doctor Robot

    Programming-Csharp اموزش 0 تا 100 c#

    حذف و اضافه کردن چند آیتم می‌توان با استفاده از متدهای ()AddRange و ()RemoveRange چندین آیتم را از آرایه حذف یا به آن اضافه نمود. متد ()AddRange می‌تواند آرایه‌ای از چند مقدار را گرقته و آنها را به شی ArrayList اضافه کند. ArrayList myArray = new ArrayList(); myArray.Add(1); myArray.Add(2); int[] numbers = { 3, 4, 5 }; myArray.AddRange(numbers); foreach(object element in myArray) { Console.WriteLine(element); } خروجی کد: 1 2 3 4 5 متد ()RemoveRange کاملاً با متد ()AddRange متفاوت است. این متد دو پارامتر قبول می‌کند، اندیس عنصری که فرایند حذف از آن شروع می‌شود و تعداد عناصری که می‌خواهیم حذف کنیم. به عنوان مثال اگر بخواهید عناصر 2 تا 6 را حذف کنید باید تکه کد زیر را بنویسید : myArray.RemoveRange(2, 5);
  24. Doctor Robot

    Programming-Csharp اموزش 0 تا 100 c#

    کلاس ArrayList کلاس ArrayList به شما اجازه ذخیره مقادیر انواع داده‌ای مختلف، و توانایی حذف و اضافه عناصر آرایه در هر لحظه را می‌دهد. در مثال زیر به سادگی کاربرد کلاس ArrayList آمده است. using System; using System.Collections; public class Program { public static void Main() { ArrayList myArray = new ArrayList(); myArray.Add("John"); myArray.Add(5); myArray.Add(true); myArray.Add(3.65); myArray.Add('R'); foreach (object element in myArray) { Console.WriteLine(element.ToString()); } } } خروجی کد: John 5 true 3.65 R برای استفاده از این کلاس ابتدا باید در قسمت فضاهای نامی، فضای نام System.Collections را وارد کنیم (خط 2). همانطور که در مثال مشاهده می‌کنید یک نمونه از کلاس ArrayList ایجاد می‌کنیم. برای اضافه کردن یک عنصر به آرایه باید از متد ()Add استفاده کنیم. از آنجاییکه شی ایجاد شده از کلاس ArrayList آرگومانی از نوع object قبول می‌کند بنابراین می‌توان مقادیری از هر نوع داده‌ای به آن ارسال کرد چون هر چیز در سی شارپ از object ارث بری می‌کند. حال برای نمایش توانایی این کلاس در نگهداری انواع داده‌ای مختلف پنج مقدار از پنج نوع مختلف داده را به آن اضافه می‌کنیم. سپس همه مقادیر را با استفاده از دستور foreach می‌خوانیم. چون کلاس ArrayList دارای انواع داده‌ای مختلفی است نمی‌توانیم از یک نوع داده‌ای خاص برای خواندن مقادیر استفاده کنیم. لذا برای این کار باید از نوع object که می‌تواند هر نوع داده‌ای در خود ذخیره کند استفاده نمود. در داخل حلقه از متد ()ToString برای نشان دادن مقادیر استفاده کرده‌ایم. به این نکته توجه کنید که برای دسترسی به هر عنصر می‌توانید از طریق اندیس آن قدام نمایید. کد زیر نحوه استفاده از حلقه for برای دسترسی به هر یک از اعضا را نشان می‌دهد. for (int i = 0; i < myArray.Count; i++) { Console.WriteLine(myArray[i].ToString()); } به خاصیت Count در کد بالا توجه کنید. این خاصیت درست شبیه به خاصیت Length آرایه معمولی است و کار آن شمارش تعداد عناصرشی ArrayList می‌باشد.. در کد بالا همانطور که نشان داده شده است می‌توان به هر یک از عناصر با استفاده از اندیسشان دست یافت. نکته دیگر این است که شما می‌توانید به کلاس ArrayList یک ظرفیت ابتدایی بدهید. به عنوان مثال شما می‌توانید با استفاده از یک سازنده سربارگذاری شده نشان دهید که یکشی ArrayList می‌تواند دارای 5 عنصر باشد. ArrayList myArray = new ArrayList(5); کد بالا 5 مکان خالی به وجود می‌آورد و شما می‌توانید با استفاده از متد ()Add یکی دیگر به آنها اضافه کنید. اگر همه مکانها به وسیله مقادیر پر شوند می‌توان سایزشی ایجاد شده از کلاس ArrayList را با استفاده از تغییر خاصیت Capacity آن تغییر داد. یکی دیگر از نسخه‌های سازنده کلاس ArrayList شیئی که رابط Icollection را اجرا می‌کند را قبول می‌کند. System.Array مثالی از این شیء است. بنابراین شما یک آرایه را به سازنده ارسال می‌کنید و مقادیر آن آرایه در شیء ArrayList کپی می‌شوند. object[] array = {"John", 5, true, 3.65, 'R' }; ArrayList myArray = new ArrayList(array); می‌توان با استفاده از متد ()Remove کلاس ArrayList عناصر را پاک کرد. متد ()Remove یک شیء که مطابق مقدار یک عنصر در آرایه است را قبول می‌کند. این متد به محض رسیدن به مقدار مورد نظر آن را حذف می‌کند. اگر عنصری را که مکانی غیر از مکان آخر آرایه باشد حذف کنید بقیه عناصر بعد از آن عنصر مکان خود را تنظیم می‌کنند به این معنی که فرض کنید آرایه‌ای دارای 5 عنصر است و شما عنصر 3 را حذف می‌کنید، در این صورت جای خالی این عنصر توسط عنصر 4 و جای عنصر 4 توسط عنصر 5 پر می‌شود. به تکه کد زیر توجه کنید : using System; using System.Collections; public class Program { public static void Main() { ArrayList myArray = new ArrayList(); myArray.Add("John"); myArray.Add(5); myArray.Add(true); myArray.Add(3.65); myArray.Add('R'); for (int i = 0; i < myArray.Count; i++) { Console.WriteLine("myArray[{0}] = {1}", i, myArray[i]); } //Remove element number 1 myArray.Remove(5); Console.WriteLine("nAfter removing myArray[1] (The value 5)...n"); for (int i = 0; i < myArray.Count; i++) { Console.WriteLine("myArray[{0}] = {1}", i, myArray[i]); } } } خروجی کد: myArray[0] = John myArray[1] = 5 myArray[2] = True myArray[3] = 3.65 myArray[4] = R After removing myArray[1] (The value 5)... myArray[0] = John myArray[1] = True myArray[2] = 3.65 myArray[3] = R از آنجاییکه در مثال بالا مقدار عنصر myArray[1] را حذف کرده‌ایم همه عناصر متوالی در آرایه بالا مکان خود را تغییر می‌دهند. بنابراین عنصر myArray[2] جای myArray[1]، عنصر myArray[3] جای myArray[2] و …را می‌گیرد. شما همچنین می‌توانید با استفاده از متد ()RemoveAt به اندیس آرایه خاصی دست یافته و آن را حذف نمایید. این متد یک پارامتر قبول می‌کند و آن اندیس عنصری است که می‌خواهید از آرایه حذف کنید.
  25. Doctor Robot

    Programming-Csharp اموزش 0 تا 100 c#

    کلکسیون ها (Collections ) قبلاً یاد گرفتیم که آرایه‌ها به ما اجازه ذخیره چندین مقدار از یک نوع را می‌دهند. آرایه‌ها از کلاس مجرد System.Array ارث بری می‌کنند که این کلاس دارای خواص و متدهایی برای کار با داده‌های ساده‌ای مانند طول آرایه می‌باشد. آرایه‌های ساده در سی شارپ دارای طول ثابتی هستند که یک بار تعریف و مقداردهی می‌شوند و شما نمی‌توانید طول یک آرایه خاص را افزایش یا کاهش دهید. دات نت گزینه بهتری برای جایگزین کردن با آرایه‌ها پیشنهاد می‌دهد و بیشتر آن‌ها کلاس‌ها و رابطهایی هستند که، در فضای نام System.Collections قرار دارند. به عنوان مثال کلاس ArrayList رفتاری شبیه به یک آرایه معمولی دارد با این تفاوت که به شما اجازه می‌دهد که طول آن را به صورت پویا تغییر داده یا یک عنصر را در طول اجرای برنامه به آن اضافه کرده و یا از آن حذف نمایید. در درس بعد پی می‌برید که چگونه یک کلاس که شامل مجموعه‌ای از اشیاء است را به وسیله اجرا کردن و یا ارث بری از رابط‌ها و متدها ایجاد کنیم.
×
×
  • جدید...