eitaa logo
برنامه نویسی سی شارپ
272 دنبال‌کننده
173 عکس
167 ویدیو
114 فایل
❁﷽❁ 👨‍🏫 Admin: @alialirezapanahi برنامه نویسی برنامه نویسی وب eitaa.com/aspdatnet پروژه ASP.Net Core MVC (پروژه وب و سی شارپ) eitaa.com/projectall ویراستی virasty.com/alialirezapanahi آپارات aparat.com/alialirezapan
مشاهده در ایتا
دانلود
خیلی خوب، رسیدیم به درس یازدهم: کلاس‌های استاتیک (Static) و نمونه (Instance). این درس خیلی مهم است چون خیلی از برنامه‌نویسان تازه‌کار فرق بین static و غیر static را اشتباه می‌گیرند. یک پروژه جدید بسازید (dotnet new console) و کدها را همراه من بنویسید و اجرا کنید. --- 📘 درس یازدهم – کلاس‌های استاتیک و نمونه 🎯 سرفصل‌ها: 1. تفاوت استاتیک و نمونه (Instance) 2. فیلد استاتیک 3. متد استاتیک 4. کلاس استاتیک 5. سازنده استاتیک 6. کلاس Math و Console مثال واقعی 7. تمرین جامع --- ⏱️ قسمت 1: تفاوت استاتیک و نمونه تصور کنید کلاس یک قالب کلوچه است: مفهوم توضیح نمونه (Instance) هر کلوچه (با شکل و اندازه خودش) استاتیک (Static) قالب کلوچه (یک نسخه مشترک بین همه) csharp class Cookie { // فیلد نمونه (هر کلوچه یک مقدار جدا دارد) public string Shape { get; set; } // فیلد استاتیک (بین همه کلوچه‌ها مشترک است) public static string MoldType = "Metal Mold"; } // استفاده Cookie cookie1 = new Cookie(); Cookie cookie2 = new Cookie(); cookie1.Shape = "Star"; cookie2.Shape = "Heart"; Console.WriteLine(cookie1.Shape); // Star Console.WriteLine(cookie2.Shape); // Heart // فیلد استاتیک: از طریق کلاس دسترسی داریم، نه نمونه Console.WriteLine(Cookie.MoldType); // Metal Mold 📌 نکته طلایی: · اعضای نمونه (Instance) به هر شیء تعلق دارند (هر کدام مقدار خودش را دارد) · اعضای استاتیک (Static) به کلاس تعلق دارند (یک مقدار برای همه) --- ⏱️ قسمت 2: فیلد استاتیک فیلدهای استاتیک بین همه نمونه‌های کلاس مشترک هستند. csharp class BankAccount { public string Owner { get; set; } public double Balance { get; set; } // فیلد استاتیک - تعداد کل حساب‌های ساخته شده public static int TotalAccounts = 0; public BankAccount(string owner, double balance) { Owner = owner; Balance = balance; TotalAccounts++; // هر بار یک حساب ساخته می‌شود، این عدد زیاد می‌شود } } // استفاده BankAccount acc1 = new BankAccount("Ali", 1000); BankAccount acc2 = new BankAccount("Sara", 2000); BankAccount acc3 = new BankAccount("Reza", 1500); Console.WriteLine($"Total accounts: {BankAccount.TotalAccounts}"); // 3 // ❌ acc1.TotalAccounts - نمی‌توان از نمونه دسترسی داشت --- ⏱️ قسمت 3: متد استاتیک متدهای استاتیک به کلاس تعلق دارند، نه به نمونه. csharp class MathHelper { // متد استاتیک - نیازی به ساختن شیء نیست public static int Add(int a, int b) { return a + b; } public static int Multiply(int a, int b) { return a * b; } public static bool IsEven(int number) { return number % 2 == 0; } } // استفاده - بدون ساختن شیء! int sum = MathHelper.Add(5, 3); int product = MathHelper.Multiply(4, 5); bool even = MathHelper.IsEven(10); Console.WriteLine($"Sum: {sum}"); // 8 Console.WriteLine($"Product: {product}"); // 20 Console.WriteLine($"Is 10 even? {even}"); // True فرق متد استاتیک و نمونه: csharp class Calculator { // متد نمونه (Instance) public int InstanceAdd(int a, int b) { return a + b; } // متد استاتیک (Static) public static int StaticAdd(int a, int b) { return a + b; } } // استفاده Calculator calc = new Calculator(); // باید شیء بسازیم int result1 = calc.InstanceAdd(5, 3); // ✅ int result2 = Calculator.StaticAdd(5, 3); // ✅ بدون ساختن شیء // int result3 = calc.StaticAdd(5, 3); // ❌ نمی‌توان از نمونه صدا زد --- ⏱️ قسمت 4: کلاس استاتیک کلاس استاتیک = کلاسی که نمی‌توان از آن شیء ساخت.
`
csharp static class Utility { // فقط می‌تواند اعضای استاتیک داشته باشد public static double PI = 3.14159; public static double CircleArea(double radius) { return PI * radius * radius; } public static string ToTitleCase(string text) { if (string.IsNullOrEmpty(text)) return text; return char.ToUpper(text[0]) + text.Substring(1).ToLower(); } } // استفاده // Utility u = new Utility(); // ❌ خطا - نمی‌توان از کلاس استاتیک شیء ساخت double area = Utility.CircleArea(5); string title = Utility.ToTitleCase("hello world");
Console.WriteLine($"Area: {area:F2}"); // 78.54 Console.WriteLine($"Title: {title}"); // Hello world 📌 قوانین کلاس استاتیک: · نمی‌توان از آن نمونه (Object) ساخت · فقط می‌تواند اعضای استاتیک داشته باشد · نمی‌تواند سازنده نمونه (instance constructor) داشته باشد · به طور خودکار sealed است (نمی‌توان از آن ارث برد) --- ⏱️ قسمت 5: سازنده استاتیک (Static Constructor) سازنده استاتیک یک بار و قبل از اولین استفاده از کلاس اجرا می‌شود. csharp class Database { public static string ConnectionString; public static int ConnectionCount; // سازنده استاتیک - یک بار اجرا می‌شود static Database() { Console.WriteLine("Static constructor called"); ConnectionString = "Server=localhost;Database=MyDB"; ConnectionCount = 0; } // متد استاتیک public static void Connect() { ConnectionCount++; Console.WriteLine($"Connected to {ConnectionString}"); Console.WriteLine($"Total connections: {ConnectionCount}"); } } // استفاده Console.WriteLine("Before first use"); Database.Connect(); // اولین استفاده → سازنده استاتیک اجرا می‌شود Database.Connect(); // سازنده استاتیک دیگر اجرا نمی‌شود Database.Connect(); خروجی: Before first use Static constructor called Connected to Server=localhost;Database=MyDB Total connections: 1 Connected to Server=localhost;Database=MyDB Total connections: 2 Connected to Server=localhost;Database=MyDB Total connections: 3 --- ⏱️ قسمت 6: مثال واقعی – کلاس Math و Console کلاس‌هایی که روزانه استفاده می‌کنیم، استاتیک هستند: csharp // کلاس Math - کاملاً استاتیک double max = Math.Max(10, 20); // 20 double min = Math.Min(10, 20); // 10 double sqrt = Math.Sqrt(25); // 5 double power = Math.Pow(2, 3); // 8 double pi = Math.PI; // 3.14159... double abs = Math.Abs(-5); // 5 // کلاس Console - استاتیک Console.WriteLine("Hello"); // چاپ string input = Console.ReadLine(); // ورودی // کلاس Convert - استاتیک int num = Convert.ToInt32("123"); double d = Convert.ToDouble("3.14"); --- ⏱️ قسمت 7: ترکیب استاتیک و نمونه می‌توانیم در یک کلاس هم عضو استاتیک و هم عضو نمونه داشته باشیم. csharp class Employee { // فیلدهای نمونه public string Name { get; set; } public int Id { get; set; } public double Salary { get; set; } // فیلد استاتیک private static int nextId = 1000; public static string CompanyName = "TechCorp"; public static int TotalEmployees = 0; // سازنده نمونه public Employee(string name, double salary) { Name = name; Salary = salary; Id = nextId++; TotalEmployees++; Console.WriteLine($"Employee {Name} created with ID {Id}"); } // متد نمونه (می‌تواند به استاتیک دسترسی داشته باشد) public void ShowInfo() { Console.WriteLine($"ID: {Id}, Name: {Name}, Salary: {Salary:C}"); Console.WriteLine($"Company: {Employee.CompanyName}"); Console.WriteLine($"Total employees: {Employee.TotalEmployees}"); } // متد استاتیک (نمی‌تواند به اعضای نمونه دسترسی داشته باشد) public static void ShowCompanyInfo() { Console.WriteLine($"Company: {CompanyName}"); Console.WriteLine($"Total employees: {TotalEmployees}"); // Console.WriteLine(Name); // ❌ خطا - Name عضو نمونه است } } // استفاده Employee emp1 = new Employee("Ali", 5000000); Employee emp2 = new Employee("Sara", 6000000); Employee emp3 = new Employee("Reza", 5500000); Console.WriteLine(); emp1.ShowInfo(); Console.WriteLine(); Employee.ShowCompanyInfo(); --- ⏱️ قسمت 8: متد استاتیک در کلاس غیر استاتیک کلاس غیر استاتیک می‌تواند متد استاتیک داشته باشد. csharp class StringHelper { // متد استاتیک public static string Reverse(string text)
{ char[] chars = text.ToCharArray(); Array.Reverse(chars); return new string(chars); } public static int CountWords(string text) { if (string.IsNullOrEmpty(text)) return 0; return text.Split(' ', StringSplitOptions.RemoveEmptyEntries).Length; } // متد نمونه public string AddExclamation(string text) { return text + "!!!"; } } // استفاده string reversed = StringHelper.Reverse("hello"); Console.WriteLine(reversed); // olleh int wordCount = StringHelper.CountWords("Hello world from C#"); Console.WriteLine(wordCount); // 4 // برای متد نمونه باید شیء بسازیم StringHelper helper = new StringHelper(); string excited = helper.AddExclamation("Hello"); Console.WriteLine(excited); // Hello!!! --- ✅ تمرین نهایی درس یازدهم برنامه‌ای بنویسید که: 1. کلاس Product با فیلدهای نمونه (Name, Price) و فیلد استاتیک (TotalProducts, TotalValue) 2. متد نمونه ShowInfo() 3. متد استاتیک ShowSummary() 4. هر بار یک محصول جدید ساخته شود، TotalProducts و TotalValue به‌روز شود csharp using System; class Product { // فیلدهای نمونه public string Name { get; set; } public double Price { get; set; } // فیلدهای استاتیک private static int totalProducts = 0; private static double totalValue = 0; // سازنده public Product(string name, double price) { Name = name; Price = price; totalProducts++; totalValue += price; Console.WriteLine($"Product '{name}' created with price {price:C}"); } // متد نمونه public void ShowInfo() { Console.WriteLine($"Product: {Name}, Price: {Price:C}"); } // متد استاتیک برای نمایش خلاصه public static void ShowSummary() { Console.WriteLine("\n=== Store Summary ==="); Console.WriteLine($"Total Products: {totalProducts}"); Console.WriteLine($"Total Inventory Value: {totalValue:C}"); Console.WriteLine($"Average Price: {(totalProducts > 0 ? totalValue / totalProducts : 0):C}"); } // متد استاتیک برای محاسبه تخفیف public static double ApplyDiscount(double price, double discountPercent) { return price * (1 - discountPercent / 100); } } class Program { static void Main() { // ساختن محصولات Product p1 = new Product("Laptop", 15000000); Product p2 = new Product("Mouse", 250000); Product p3 = new Product("Keyboard", 850000); Product p4 = new Product("Monitor", 5500000); Console.WriteLine(); // نمایش اطلاعات هر محصول p1.ShowInfo(); p2.ShowInfo(); p3.ShowInfo(); p4.ShowInfo(); // نمایش خلاصه فروشگاه Product.ShowSummary(); // استفاده از متد استاتیک تخفیف double discountedPrice = Product.ApplyDiscount(15000000, 15); Console.WriteLine($"\nLaptop with 15% discount: {discountedPrice:C}"); Console.WriteLine("\nPress Enter to exit..."); Console.ReadLine(); } } --- 📌 جمع‌بندی درس یازدهم مفهوم مثال دسترسی فیلد نمونه public string Name از طریق شیء فیلد استاتیک public static int Count از طریق کلاس متد نمونه public void Show() از طریق شیء متد استاتیک public static void Calc() از طریق کلاس کلاس استاتیک static class Utility نمی‌توان شیء ساخت قوانین مهم: 1. متد استاتیک نمی‌تواند به عضو نمونه دسترسی داشته باشد csharp static void Method() { Name = "Ali"; } // ❌ اگر Name نمونه باشد 2. متد نمونه می‌تواند به عضو استاتیک دسترسی داشته باشد csharp void Method() { Count = 10; } // ✅ اگر Count استاتیک باشد
`
3. کلاس استاتیک فقط عضو استاتیک می‌تواند داشته باشد --- 🧪 تمرین برای شما 1. کلاس Counter بسازید با: · فیلد استاتیک totalCount
· متد استاتیک Increment() · متد استاتیک GetCount() · از چند جا صدا بزنید و نتیجه را ببینید 2. کلاس Configuration بسازید با: · فیلدهای استاتیک: AppName, Version, Theme · سازنده استاتیک برای مقداردهی اولیه 3. برنامه‌ای بنویسید که تعداد دفعاتی که یک متد صدا زده شده را با فیلد استاتیک بشمارد --- اگر این درس را کامل فهمیدید، بگویید تا درس دوازدهم (Enum و Struct) را شروع کنیم. سوالی بود بپرسید.
خیلی خوب، رسیدیم به درس دوازدهم: Enum (شمارنده‌ها) و Struct (ساختارها). این دو نوع داده به شما کمک می‌کنند کد خواناتر و منظم‌تری بنویسید. یک پروژه جدید بسازید (dotnet new console) و کدها را همراه من بنویسید و اجرا کنید. --- 📘 درس دوازدهم – Enum و Struct 🎯 سرفصل‌ها: 1. Enum چیست و چرا نیاز داریم؟ 2. تعریف و استفاده از Enum 3. مقداردهی عددی به Enum 4. تبدیل Enum به عدد و متن 5. Struct چیست؟ 6. تفاوت Struct با Class 7. استفاده از Struct 8. تمرین جامع --- ⏱️ قسمت 1: Enum چیست؟ Enum = مجموعه‌ای از ثابت‌های نام‌دار بدون Enum (کد بد): csharp int userRole = 1; // 1=admin, 2=user, 3=guest if (userRole == 1) { Console.WriteLine("Welcome Admin"); } // مشکل: عدد 1 یعنی چه؟ یادم می‌رود! با Enum (کد خوب): csharp enum UserRole { Admin, User, Guest } UserRole role = UserRole.Admin; if (role == UserRole.Admin) { Console.WriteLine("Welcome Admin"); } --- ⏱️ قسمت 2: تعریف و استفاده از Enum csharp // تعریف Enum (معمولاً بیرون از کلاس) enum Days { Saturday, Sunday, Monday, Tuesday, Wednesday, Thursday, Friday } enum Status { Pending, Approved, Rejected, Shipped } // استفاده Days today = Days.Wednesday; Status orderStatus = Status.Approved; Console.WriteLine($"Today is: {today}"); Console.WriteLine($"Order status: {orderStatus}"); // استفاده در شرط if (orderStatus == Status.Approved) { Console.WriteLine("Your order is approved!"); } --- ⏱️ قسمت 3: مقداردهی عددی به Enum به طور پیش‌فرض، اعضای Enum از 0 شروع می‌شوند. csharp enum Priority { Low = 1, // مقدار 1 Medium = 2, // مقدار 2 High = 3, // مقدار 3 Urgent = 10 // مقدار 10 } enum Color { Red = 10, Green = 20, Blue = 30 } // استفاده Priority taskPriority = Priority.High; Console.WriteLine(taskPriority); // High Console.WriteLine((int)taskPriority); // 3 Priority urgent = Priority.Urgent; Console.WriteLine((int)urgent); // 10 مقداردهی خودکار: csharp enum ErrorCode { None = 0, NotFound = 100, Unauthorized = 101, ServerError = 500 } --- ⏱️ قسمت 4: تبدیل Enum به عدد و متن csharp enum Season { Spring = 1, Summer = 2, Autumn = 3, Winter = 4 } // Enum به عدد Season current = Season.Summer; int seasonNumber = (int)current; Console.WriteLine(seasonNumber); // 2 // عدد به Enum int input = 3; Season parsedSeason = (Season)input; Console.WriteLine(parsedSeason); // Autumn // Enum به متن string seasonName = current.ToString(); Console.WriteLine(seasonName); // Summer // متن به Enum string userInput = "Winter"; Season selected = (Season)Enum.Parse(typeof(Season), userInput); Console.WriteLine(selected); // Winter // روش امن برای تبدیل (بدون خطا) if (Enum.TryParse("Spring", out Season result)) { Console.WriteLine($"Parsed: {result}"); } --- ⏱️ قسمت 5: Struct چیست؟ Struct = یک نوع مقدار (Value Type) که داده‌های کوچک را نگهداری می‌کند. تعریف Struct: csharp struct Point { public int X; public int Y; public Point(int x, int y) { X = x; Y = y; } public double DistanceFromOrigin() { return Math.Sqrt(X * X + Y * Y); } } // استفاده Point p1; p1.X = 10; p1.Y = 20; Point p2 = new Point(5, 7); Point p3 = new Point(); // تمام فیلدها پیش‌فرض (0) Console.WriteLine($"p1: ({p1.X}, {p1.Y})"); Console.WriteLine($"p2: ({p2.X}, {p2.Y})"); Console.WriteLine($"p3: ({p3.X}, {p3.Y})"); Console.WriteLine($"Distance: {p2.DistanceFromOrigin():F2}"); --- ⏱️ قسمت 6: تفاوت Struct با Class (خیلی مهم) ویژگی Class Struct نوع Reference Type (ارجاعی) Value Type (مقداری) مکان در حافظه Heap Stack ارث‌بری دارد ندارد سازنده پیش‌فرض دارد نمی‌توان داشت مقایسه مرجع را مقایسه می‌کند مقدار را مقایسه می‌کند سرعت برای داده کوچک کندتر سریعتر استفاده برای داده‌های بزرگ داده‌های کوچک (کمتر از 16 بایت)
`
csharp // کلاس (Reference Type) class PointClass { public int X { get; set; } public int Y { get; set; } public PointClass(int x, int y) { X = x; Y = y; } }
// Struct (Value Type) struct PointStruct { public int X { get; set; } public int Y { get; set; } public PointStruct(int x, int y) { X = x; Y = y; } } // تفاوت در عمل PointClass c1 = new PointClass(5, 5); PointClass c2 = c1; // c2 به همان شیء اشاره می‌کند c2.X = 10; Console.WriteLine($"c1.X = {c1.X}"); // 10 (تغییر کرد!) PointStruct s1 = new PointStruct(5, 5); PointStruct s2 = s1; // کپی از مقدار s2.X = 10; Console.WriteLine($"s1.X = {s1.X}"); // 5 (تغییر نکرد!) --- ⏱️ قسمت 7: مثال‌های کاربردی Struct Struct برای مختصات RGB: csharp struct RGBColor { public byte Red; public byte Green; public byte Blue; public RGBColor(byte red, byte green, byte blue) { Red = red; Green = green; Blue = blue; } public string GetHexCode() { return $"#{Red:X2}{Green:X2}{Blue:X2}"; } public string GetName() { if (Red == 255 && Green == 0 && Blue == 0) return "Red"; if (Red == 0 && Green == 255 && Blue == 0) return "Green"; if (Red == 0 && Green == 0 && Blue == 255) return "Blue"; if (Red == 255 && Green == 255 && Blue == 255) return "White"; if (Red == 0 && Green == 0 && Blue == 0) return "Black"; return "Custom Color"; } } // استفاده RGBColor red = new RGBColor(255, 0, 0); RGBColor custom = new RGBColor(128, 200, 50); Console.WriteLine(red.GetHexCode()); // Console.WriteLine(red.GetName()); // Red Console.WriteLine(custom.GetHexCode()); // Console.WriteLine(custom.GetName()); // Custom Color Struct برای محدوده (Range): csharp struct Range { public int Start; public int End; public Range(int start, int end) { if (start > end) throw new ArgumentException("Start must be less than or equal to End"); Start = start; End = end; } public int Length => End - Start + 1; public bool Contains(int value) { return value >= Start && value <= End; } public int[] ToArray() { int[] result = new int[Length]; for (int i = 0; i < Length; i++) { result[i] = Start + i; } return result; } } // استفاده Range range = new Range(1, 10); Console.WriteLine($"Length: {range.Length}"); // 10 Console.WriteLine($"Contains 5: {range.Contains(5)}"); // True Console.WriteLine($"Contains 15: {range.Contains(15)}"); // False int[] numbers = range.ToArray(); Console.WriteLine(string.Join(", ", numbers)); // 1,2,3,4,5,6,7,8,9,10 --- ⏱️ قسمت 8: Struct در مقابل Class – کدام را استفاده کنیم؟ از Struct استفاده کنید وقتی: · داده‌ها کوچک هستند (کمتر از 16 بایت) · نیاز به کپی کردن مکرر دارید · نیازی به ارث‌بری ندارید · نوع داده ساده و مستقل است (مثل نقطه، رنگ، محدوده) از Class استفاده کنید وقتی: · داده‌ها بزرگ هستند · نیاز به ارث‌بری دارید · نیاز به رفتارهای پیچیده دارید · شیء باید قابلیت تغییر (Mutable) داشته باشد csharp // خوب برای Struct (داده کوچک) struct Coordinate { public double Latitude; public double Longitude; } struct Size { public int Width; public int Height; } // خوب برای Class (داده بزرگ و رفتار پیچیده) class Customer { public string Name { get; set; } public string Email { get; set; } public List<Order> Orders { get; set; } } --- ✅ تمرین نهایی درس دوازدهم برنامه‌ای بنویسید که: 1. Enum ای برای OrderStatus (Pending, Processing, Shipped, Delivered, Cancelled) 2. Struct ای برای Product (Name, Price, Quantity) 3. Struct ای برای Order (Id, CustomerName, List<Product>, Status) 4. امکانات: افزودن محصول، نمایش سفارش، تغییر وضعیت csharp using System; using System.Collections.Generic; enum OrderStatus { Pending, Processing, Shipped, Delivered, Cancelled }
struct Product { public string Name; public double Price; public int Quantity; public Product(string name, double price, int quantity) { Name = name; Price = price; Quantity = quantity; } public double TotalPrice => Price * Quantity; public void Display() { Console.WriteLine($" - {Name}: {Quantity} x {Price:C} = {TotalPrice:C}"); } } struct Order { public int Id; public string CustomerName; public List<Product> Products; public OrderStatus Status; public Order(int id, string customerName) { Id = id; CustomerName = customerName; Products = new List<Product>(); Status = OrderStatus.Pending; } public void AddProduct(Product product) { Products.Add(product); Console.WriteLine($"Added {product.Quantity}x {product.Name} to order #{Id}"); } public double GetTotal() { double total = 0; foreach (Product p in Products) { total += p.TotalPrice; } return total; } public void ChangeStatus(OrderStatus newStatus) { Status = newStatus; Console.WriteLine($"Order #{Id} status changed to {Status}"); } public void Display() { Console.WriteLine($"\n=== Order #{Id} ==="); Console.WriteLine($"Customer: {CustomerName}"); Console.WriteLine($"Status: {Status}"); Console.WriteLine("Products:"); if (Products.Count == 0) { Console.WriteLine(" (empty)"); } else { foreach (Product p in Products) { p.Display(); } } Console.WriteLine($"Total: {GetTotal():C}"); Console.WriteLine("================="); } } class Program { static void Main() { // ساخت سفارش Order order1 = new Order(1001, "Ali Mohammadi"); Order order2 = new Order(1002, "Sara Ahmadi"); // افزودن محصولات Console.WriteLine("=== Adding Products ==="); order1.AddProduct(new Product("Laptop", 15000000, 1)); order1.AddProduct(new Product("Mouse", 250000, 2)); order2.AddProduct(new Product("Keyboard", 850000, 1)); order2.AddProduct(new Product("Monitor", 5500000, 1)); order2.AddProduct(new Product("Headphones", 1200000, 1)); // نمایش سفارش‌ها order1.Display(); order2.Display(); // تغییر وضعیت Console.WriteLine("\n=== Status Updates ==="); order1.ChangeStatus(OrderStatus.Processing); order1.ChangeStatus(OrderStatus.Shipped); order2.ChangeStatus(OrderStatus.Delivered); // نمایش نهایی order1.Display(); order2.Display(); Console.WriteLine("\nPress Enter to exit..."); Console.ReadLine(); } }
`
--- 📌 جمع‌بندی درس دوازدهم مفهوم کاربرد مثال Enum مجموعه ثابت‌های نام‌دار Days.Monday Struct نوع مقدار برای داده‌های کوچک Point p = new Point(10, 20) Class نوع مرجع برای داده‌های بزرگ Customer c = new Customer() نکات کلیدی Enum: · مقادیر از 0 شروع می‌شوند (قابل تغییر) · می‌توان به عدد و متن تبدیل کرد · قابلیت خواندن کد را بالا می‌برد نکات کلیدی Struct: · نوع مقدار (Value Type) است · روی Stack ذخیره می‌شود · سریعتر از Class برای داده‌های کوچک · نمی‌توان از آن ارث برد · مقایسه بر اساس مقادیر است نه مرجع --- 🧪 تمرین برای شما 1. Enum ای برای Month (12 ماه) بسازید و برنام‌های بنویسید که تعداد روزهای هر ماه را چاپ کند 2. Struct ای برای Time (Hour, Minute, Second) بسازید با متد ToSeconds() و ToString() 3. Struct ای برای Fraction (صورت و مخرج) بسازید با متد‌های جمع، تفریق، ضرب و تقسیم 4. تفاوت عملی Struct و Class را با یک مثال نشان دهید (نشان دهید کپی شدن چطور کار می‌کند) --- اگر این درس را کامل فهمیدید، بگویید تا درس سیزدهم (Delegates و Events) را شروع کنیم. سوالی بود بپرسید.
خیلی خوب، رسیدیم به درس سیزدهم: Delegates (نماینده‌ها) و Events (رویدادها). این درس کمی پیشرفته‌تر است اما خیلی کاربردی. Delegates به شما اجازه می‌دهند متدها را به عنوان متغیر استفاده کنید. یک پروژه جدید بسازید (dotnet new console) و کدها را همراه من بنویسید و اجرا کنید. --- 📘 درس سیزدهم – Delegates و Events 🎯 سرفصل‌ها: 1. Delegate چیست؟ 2. تعریف و استفاده از Delegate 3. Multicast Delegate (چند متدی) 4. Func، Action، Predicate (Delegate‌های آماده) 5. Event چیست؟ 6. تفاوت Event با Delegate 7. مثال واقعی (دکمه کلیک) 8. تمرین جامع --- ⏱️ قسمت 1: Delegate چیست؟ Delegate = یک متغیر که می‌تواند به یک متد اشاره کند (اشاره‌گر به متد) csharp // 1. تعریف Delegate (امضای متد را مشخص می‌کند) delegate int MathOperation(int a, int b); // 2. متدهایی با همان امضا int Add(int x, int y) { return x + y; } int Multiply(int x, int y) { return x * y; } // 3. استفاده MathOperation operation = Add; // اشاره به متد Add int result1 = operation(5, 3); // 8 Console.WriteLine($"Add: {result1}"); operation = Multiply; // تغییر اشاره به متد Multiply int result2 = operation(5, 3); // 15 Console.WriteLine($"Multiply: {result2}"); 📌 Delegate مانند یک قالب است: · امضای متد را مشخص می‌کند (نوع ورودی و خروجی) · هر متدی با همین امضا را می‌توان به آن اختصاص داد --- ⏱️ قسمت 2: کاربرد واقعی Delegate csharp delegate bool FilterFunction(int number); // متدهای فیلتر bool IsEven(int n) => n % 2 == 0; bool IsGreaterThanTen(int n) => n > 10; bool IsPrime(int n) { if (n < 2) return false; for (int i = 2; i <= Math.Sqrt(n); i++) if (n % i == 0) return false; return true; } // متدی که از Delegate استفاده می‌کند int[] FilterNumbers(int[] numbers, FilterFunction filter) { List<int> result = new List<int>(); foreach (int n in numbers) { if (filter(n)) result.Add(n); } return result.ToArray(); } // استفاده int[] nums = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13 }; int[] evens = FilterNumbers(nums, IsEven); int[] greaterThanTen = FilterNumbers(nums, IsGreaterThanTen); int[] primes = FilterNumbers(nums, IsPrime); Console.WriteLine($"Evens: {string.Join(", ", evens)}"); Console.WriteLine($"Greater than 10: {string.Join(", ", greaterThanTen)}"); Console.WriteLine($"Primes: {string.Join(", ", primes)}"); --- ⏱️ قسمت 3: Multicast Delegate (چند متدی) یک Delegate می‌تواند به چندین متد اشاره کند. csharp delegate void PrintDelegate(string message); void PrintToConsole(string msg) { Console.WriteLine($"Console: {msg}"); } void PrintToFile(string msg) { Console.WriteLine($"File: [LOG] {msg}"); } void PrintToDatabase(string msg) { Console.WriteLine($"Database: storing '{msg}'"); } // استفاده از Multicast PrintDelegate printer = PrintToConsole; printer += PrintToFile; // اضافه کردن متد دوم printer += PrintToDatabase; // اضافه کردن متد سوم printer("Hello World!"); // هر سه متد اجرا می‌شوند // حذف یک متد printer -= PrintToFile; Console.WriteLine("\nAfter removing PrintToFile:"); printer("Another message"); خروجی: Console: Hello World! File: [LOG] Hello World! Database: storing 'Hello World!' After removing PrintToFile: Console: Another message Database: storing 'Another message' --- ⏱️ قسمت 4: Delegateهای آماده (Func, Action, Predicate) به جای تعریف Delegate خودمان، می‌توانیم از اینها استفاده کنیم: نوع ورودی خروجی کاربرد Action 0 تا 16 پارامتر void بدون خروجی Func 0 تا 16 پارامتر یک مقدار با خروجی Predicate 1 پارامتر bool شرط Action (بدون خروجی): csharp // Action بدون پارامتر Action sayHello = () => Console.WriteLine("Hello!"); sayHello(); // Action با یک پارامتر Action<string> greet = (name) => Console.WriteLine($"Hello {name}!"); greet("Ali"); // Action با دو پارامتر Action<string, int> introduce = (name, age) => Console.WriteLine($"I'm {name}, {age} years old"); introduce("Sara", 25); Func (با خروجی):
`
csharp // Func با یک ورودی و یک خروجی Func<int, int> square = (x) => x * x; Console.WriteLine(square(5)); // 25
// Func با دو ورودی و یک خروجی Func<int, int, int> add = (a, b) => a + b; Console.WriteLine(add(10, 20)); // 30 // Func با string ورودی و bool خروجی Func<string, bool> isEmpty = (s) => string.IsNullOrEmpty(s); Console.WriteLine(isEmpty("")); // True Console.WriteLine(isEmpty("Hi")); // False Predicate (شرط): csharp // Predicate = Func<T, bool> Predicate<int> isEven = (n) => n % 2 == 0; Console.WriteLine(isEven(4)); // True Console.WriteLine(isEven(5)); // False // استفاده در List List<int> numbers = new List<int> { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; List<int> evens = numbers.FindAll(isEven); Console.WriteLine($"Evens: {string.Join(", ", evens)}"); --- ⏱️ قسمت 5: Event چیست؟ Event = یک Delegate خاص که فقط در کلاس خودش صدا زده می‌شود. csharp class Button { // تعریف Delegate public delegate void ClickHandler(object sender, EventArgs e); // تعریف Event public event ClickHandler Click; // متد برای صدا زدن Event public void OnClick() { Console.WriteLine("Button was clicked!"); Click?.Invoke(this, EventArgs.Empty); // اگر کسی مشترک شده باشد، صدا بزن } } class Program { static void Main() { Button btn = new Button(); // اشتراک در رویداد btn.Click += Button_Click; btn.Click += Button_Click2; // شبیه‌سازی کلیک btn.OnClick(); } static void Button_Click(object sender, EventArgs e) { Console.WriteLine("Event handler 1 executed"); } static void Button_Click2(object sender, EventArgs e) { Console.WriteLine("Event handler 2 executed"); } } --- ⏱️ قسمت 6: تفاوت Event با Delegate ویژگی Delegate Event قابل صدا زدن از بیرون ✅ ❌ (فقط داخل کلاس) قابل اشتراک از بیرون ✅ ✅ (با +=) قابل لغو اشتراک از بیرون ✅ ✅ (با -=) قابل مقداردهی از بیرون ✅ (=) ❌ (فقط += و -=) csharp class Test { public delegate void MyDelegate(string msg); public MyDelegate Del; // Delegate معمولی public event MyDelegate Evt; // Event public void TestMethod() { Del("From inside"); // ✅ Evt("From inside"); // ✅ } } // در بیرون Test t = new Test(); t.Del = (msg) => Console.WriteLine(msg); // ✅ // t.Evt = (msg) => Console.WriteLine(msg); // ❌ خطا - نمی‌توان = t.Del += (msg) => Console.WriteLine(msg); // ✅ t.Evt += (msg) => Console.WriteLine(msg); // ✅ // t.Del("From outside"); // ✅ // t.Evt("From outside"); // ❌ خطا - نمی‌توان از بیرون صدا زد --- ⏱️ قسمت 7: مثال واقعی – سیستم آب و هوا csharp using System; using System.Collections.Generic; // کلاس اطلاعات آب و هوا class WeatherData { public double Temperature { get; set; } public double Humidity { get; set; } public string Condition { get; set; } public override string ToString() { return $"{Condition}, {Temperature}°C, {Humidity}% humidity"; } } // کلاس ایستگاه آب و هوا (منتشرکننده رویداد) class WeatherStation { // تعریف Delegate و Event public delegate void WeatherUpdateHandler(object sender, WeatherData data); public event WeatherUpdateHandler WeatherUpdated; private WeatherData currentData; public WeatherStation() { currentData = new WeatherData { Temperature = 25, Humidity = 60, Condition = "Sunny" }; } public void UpdateWeather(double temp, double humidity, string condition) { currentData.Temperature = temp; currentData.Humidity = humidity; currentData.Condition = condition; Console.WriteLine($"\n[WeatherStation] Weather updated: {currentData}"); // اطلاع به مشترکین WeatherUpdated?.Invoke(this, currentData); } } // کلاس نمایشگر (مشترک رویداد) class DisplayScreen { private string name; public DisplayScreen(string screenName) { name = screenName; } public void OnWeatherUpdated(object sender, WeatherData data) { Console.WriteLine($"[{name}] Displaying: {data}"); } }
// کلاس هشداردهنده (مشترک دیگر) class AlertSystem { public void OnWeatherUpdated(object sender, WeatherData data) { if (data.Temperature > 35) Console.WriteLine($"[Alert] HEAT WARNING! {data.Temperature}°C"); else if (data.Temperature < 0) Console.WriteLine($"[Alert] FREEZE WARNING! {data.Temperature}°C"); else if (data.Humidity > 80) Console.WriteLine($"[Alert] HIGH HUMIDITY! {data.Humidity}%"); } } // برنامه اصلی class Program { static void Main() { WeatherStation station = new WeatherStation(); DisplayScreen screen1 = new DisplayScreen("Living Room"); DisplayScreen screen2 = new DisplayScreen("Phone App"); AlertSystem alerts = new AlertSystem(); // اشتراک در رویداد station.WeatherUpdated += screen1.OnWeatherUpdated; station.WeatherUpdated += screen2.OnWeatherUpdated; station.WeatherUpdated += alerts.OnWeatherUpdated; // به‌روزرسانی آب و هوا station.UpdateWeather(28, 55, "Sunny"); station.UpdateWeather(38, 45, "Hot"); station.UpdateWeather(-2, 70, "Snowy"); station.UpdateWeather(30, 85, "Rainy"); Console.WriteLine("\nPress Enter to exit..."); Console.ReadLine(); } } --- ✅ تمرین نهایی درس سیزدهم برنامه‌ای بنویسید که: 1. کلاس BankAccount با رویداد BalanceChanged 2. وقتی موجودی تغییر کرد، چندین مشترک مطلع شوند 3. از Action و Func در متدهای مختلف استفاده کنید csharp using System; class BankAccount { private double balance; // تعریف رویداد public event Action<object, double, double> BalanceChanged; // sender, oldBalance, newBalance public string AccountNumber { get; set; } public string Owner { get; set; } public double Balance { get { return balance; } private set { double oldBalance = balance; balance = value; // صدا زدن رویداد BalanceChanged?.Invoke(this, oldBalance, balance); } } public BankAccount(string number, string owner, double initialBalance) { AccountNumber = number; Owner = owner; balance = initialBalance; } public void Deposit(double amount) { if (amount > 0) { Balance += amount; Console.WriteLine($"Deposited: {amount:C}"); } } public void Withdraw(double amount) { if (amount > 0 && amount <= Balance) { Balance -= amount; Console.WriteLine($"Withdrawn: {amount:C}"); } else { Console.WriteLine("Insufficient balance or invalid amount!"); } } } class Program { static void Main() { BankAccount account = new BankAccount("123456789", "Ali Rezaei", 1000000); // مشترکین رویداد account.BalanceChanged += OnBalanceChanged_Logger; account.BalanceChanged += OnBalanceChanged_Email; account.BalanceChanged += OnBalanceChanged_SMS; // انجام عملیات Console.WriteLine("=== Bank Account Transactions ===\n"); account.Deposit(500000); account.Withdraw(200000); account.Withdraw(1500000); // ناموفق account.Deposit(1000000); Console.WriteLine("\nPress Enter to exit..."); Console.ReadLine(); } static void OnBalanceChanged_Logger(object sender, double oldBalance, double newBalance) { BankAccount acc = (BankAccount)sender; Console.WriteLine($"[LOG] Account {acc.AccountNumber}: {oldBalance:C} → {newBalance:C}"); } static void OnBalanceChanged_Email(object sender, double oldBalance, double newBalance)
{ BankAccount acc = (BankAccount)sender; Console.WriteLine($"[EMAIL] Dear {acc.Owner}, your balance changed to {newBalance:C}"); } static void OnBalanceChanged_SMS(object sender, double oldBalance, double newBalance) { Console.WriteLine($"[SMS] Balance update: {newBalance:C}"); } }
`
--- 📌 جمع‌بندی درس سیزدهم مفهوم توضیح مثال delegate تعریف نماینده delegate int MyDel(int x); Action Delegate بدون خروجی Action<string> print = s => Console.WriteLine(s); Func Delegate با خروجی Func<int,int> square = x => x*x; Predicate Delegate شرط Predicate<int> isEven = n => n%2==0; event رویداد (نسخه امن Delegate) public event Action MyEvent; کاربردهای اصلی: · Callback (فراخوانی بعد از انجام کار) · Event Handling (مدیریت رویدادها مانند کلیک) · LINQ (بسیاری از متدهای LINQ از Delegate استفاده می‌کنند) · ساختارهای انعطاف‌پذیر --- 🧪 تمرین برای شما 1. یک Func بنویسید که دو string بگیرد و برگرداند طول بزرگترین آنها 2. یک Action بنویسید که یک آرایه بگیرد و همه اعضا را چاپ کند 3. یک کلاس Timer بسازید با رویداد Tick که هر ثانیه یک بار صدا زده شود 4. یک برنامه سفارش آنلاین بسازید که رویدادهای OrderPlaced، OrderShipped، OrderDelivered داشته باشد --- اگر این درس را کامل فهمیدید، بگویید تا درس چهاردهم (LINQ) را شروع کنیم. سوالی بود بپرسید.
خیلی خوب، پس شروع می‌کنیم درس چهاردهم – LINQ قسمت اول: آشنایی با LINQ و متدهای پایه. یک پروژه جدید کنسولی بسازید (dotnet new console) و کدها را همراه من بنویسید و اجرا کنید. --- 📘 درس چهاردهم – LINQ قسمت 1: آشنایی با LINQ 🎯 سرفصل‌ها: 1. LINQ چیست و چرا نیاز داریم؟ 2. دو روش نوشتن LINQ (Query Syntax و Method Syntax) 3. متد Where (فیلتر کردن) 4. متد Select (انتخاب و تبدیل) 5. متدهای First، FirstOrDefault، Single، SingleOrDefault 6. متد ToList و اجرای دیررس (Deferred Execution) 7. تمرین جامع --- ⏱️ قسمت 1: LINQ چیست؟ LINQ = Language Integrated Query زبانی برای پرس و جو از داده‌ها درون خود سی‌شارپ. بدون LINQ (کد قدیمی و طولانی): csharp List<int> numbers = new List<int> { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; List<int> evens = new List<int>(); foreach (int n in numbers) { if (n % 2 == 0) { evens.Add(n); } } با LINQ (کد کوتاه و خواناتر): csharp using System.Linq; // اضافه کردن این using لازم است List<int> numbers = new List<int> { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; var evens = numbers.Where(n => n % 2 == 0).ToList(); 📌 نکته: حتماً using System.Linq; را در بالای فایل اضافه کنید. --- ⏱️ قسمت 2: دو روش نوشتن LINQ روش اول: Method Syntax (روش متدی) – رایج‌تر csharp var result = numbers.Where(n => n > 5).Select(n => n * 2); روش دوم: Query Syntax (روش شبه SQL) – شبیه به SQL csharp var result = from n in numbers where n > 5 select n * 2; مقایسه هر دو روش: csharp int[] scores = { 85, 92, 78, 90, 88, 70, 95 }; // Method Syntax var highScores1 = scores.Where(s => s >= 90).OrderBy(s => s); // Query Syntax var highScores2 = from s in scores where s >= 90 orderby s select s; Console.WriteLine("High scores (>=90):"); foreach (var score in highScores1) { Console.Write(score + " "); // 90 92 95 } 📌 نکته: هر دو روش نتیجه یکسان دارند. Method Syntax پرکاربردتر است. --- ⏱️ قسمت 3: متد Where (فیلتر کردن) Where برای فیلتر کردن داده‌ها بر اساس یک شرط استفاده می‌شود. csharp List<string> names = new List<string> { "Ali", "Reza", "Sara", "Mohammad", "Neda", "Hossein" }; // نام‌هایی که با "A" شروع می‌شوند var startsWithA = names.Where(n => n.StartsWith("A")); Console.WriteLine("Starts with A: " + string.Join(", ", startsWithA)); // نام‌هایی که طول آنها بیشتر از 4 است var longNames = names.Where(n => n.Length > 4); Console.WriteLine("Long names: " + string.Join(", ", longNames)); // ترکیب چند شرط var result = names.Where(n => n.Length > 3 && n.Contains("e")); Console.WriteLine("Long names with 'e': " + string.Join(", ", result)); --- ⏱️ قسمت 4: متد Select (انتخاب و تبدیل) Select برای تبدیل هر عنصر به شکل دیگری استفاده می‌شود. csharp List<int> numbers = new List<int> { 1, 2, 3, 4, 5 }; // تبدیل هر عدد به مربع آن var squares = numbers.Select(n => n * n); Console.WriteLine("Squares: " + string.Join(", ", squares)); // 1,4,9,16,25 // تبدیل هر عدد به متن var textNumbers = numbers.Select(n => $"Number: {n}"); foreach (var item in textNumbers) { Console.WriteLine(item); } مثال با کلاس Person: csharp class Person { public string Name { get; set; } public int Age { get; set; } public string City { get; set; } } List<Person> people = new List<Person> { new Person { Name = "Ali", Age = 25, City = "Tehran" }, new Person { Name = "Sara", Age = 30, City = "Shiraz" }, new Person { Name = "Reza", Age = 22, City = "Tehran" }, new Person { Name = "Neda", Age = 28, City = "Isfahan" } }; // فقط نام‌ها را انتخاب کن var namesOnly = people.Select(p => p.Name); Console.WriteLine("Names: " + string.Join(", ", namesOnly)); // نام و سن را به صورت یک شیء ناشناس (Anonymous) انتخاب کن var nameAndAge = people.Select(p => new { p.Name, p.Age }); foreach (var item in nameAndAge) { Console.WriteLine($"{item.Name} is {item.Age} years old"); } --- ⏱️ قسمت 5: ترکیب Where و Select
`
csharp List<int> numbers = new List<int> { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };