// چندریختی در عمل
Shape[] shapes = new Shape[3];
shapes[0] = new Circle(5);
shapes[1] = new Rectangle(4, 6);
shapes[2] = new Circle(3);
foreach (Shape shape in shapes)
{
shape.Draw();
Console.WriteLine($"Area: {shape.GetArea():F2}");
Console.WriteLine();
}
---
⏱️ قسمت 5: کلاس abstract (چکیده)
کلاس abstract = کلاسی که نمیتوان از آن شیء ساخت، فقط برای ارثبری است.
csharp
// کلاس abstract
abstract class Employee
{
public string Name { get; set; }
public int Id { get; set; }
public Employee(string name, int id)
{
Name = name;
Id = id;
}
// متد abstract - بدون بدنه، فرزند حتماً باید پیادهسازی کند
public abstract double CalculateSalary();
// متد معمولی
public void ShowInfo()
{
Console.WriteLine($"Employee: {Name} (ID: {Id})");
}
}
class FullTimeEmployee : Employee
{
public double MonthlySalary { get; set; }
public FullTimeEmployee(string name, int id, double salary) : base(name, id)
{
MonthlySalary = salary;
}
public override double CalculateSalary()
{
return MonthlySalary;
}
}
class PartTimeEmployee : Employee
{
public double HourlyRate { get; set; }
public int HoursWorked { get; set; }
public PartTimeEmployee(string name, int id, double rate, int hours) : base(name, id)
{
HourlyRate = rate;
HoursWorked = hours;
}
public override double CalculateSalary()
{
return HourlyRate * HoursWorked;
}
}
// استفاده
// Employee e = new Employee(); // ❌ خطا - نمیتوان از کلاس abstract شیء ساخت
FullTimeEmployee fte = new FullTimeEmployee("Ali", 101, 5000000);
PartTimeEmployee pte = new PartTimeEmployee("Sara", 102, 50000, 80);
fte.ShowInfo();
Console.WriteLine($"Salary: {fte.CalculateSalary()}");
pte.ShowInfo();
Console.WriteLine($"Salary: {pte.CalculateSalary()}");
---
⏱️ قسمت 6: کلاس sealed (مهر و موم شده)
کلاس sealed = کلاسی که نمیتوان از آن ارثبری کرد.
csharp
sealed class FinalClass
{
public void DoSomething()
{
Console.WriteLine("This class cannot be inherited");
}
}
// class Child : FinalClass { } // ❌ خطا - نمیتوان از sealed ارث برد
متد sealed: در کلاس فرزند، نمیتوان بیشتر از این بازنویسی کرد.
csharp
class Parent
{
public virtual void MyMethod()
{
Console.WriteLine("Parent");
}
}
class Child : Parent
{
public sealed override void MyMethod() // sealed در این سطح
{
Console.WriteLine("Child");
}
}
// class GrandChild : Child
// {
// public override void MyMethod() { } // ❌ خطا - متد sealed است
// }
---
⏱️ قسمت 7: مثال کامل – سیستم حیوانات
csharp
using System;
// کلاس abstract
abstract class Animal
{
public string Name { get; set; }
public int Age { get; set; }
public Animal(string name, int age)
{
Name = name;
Age = age;
}
public abstract void MakeSound();
public virtual void Move()
{
Console.WriteLine($"{Name} is moving");
}
public void ShowInfo()
{
Console.WriteLine($"Name: {Name}, Age: {Age}");
MakeSound();
Move();
}
}
class Dog : Animal
{
public string Breed { get; set; }
public Dog(string name, int age, string breed) : base(name, age)
{
Breed = breed;
}
public override void MakeSound()
{
Console.WriteLine($"{Name} barks: Woof! Woof!");
}
public override void Move()
{
Console.WriteLine($"{Name} runs happily");
}
}
class Bird : Animal
{
public double WingSpan { get; set; }
public Bird(string name, int age, double wingSpan) : base(name, age)
{
WingSpan = wingSpan;
}
public override void MakeSound()
{
Console.WriteLine($"{Name} chirps: Tweet! Tweet!");
}
public override void Move()
{
Console.WriteLine($"{Name} flies with {WingSpan}m wingspan");
}
}
class Fish : Animal
{
public string WaterType { get; set; } // Fresh or Salt
public Fish(string name, int age, string waterType) : base(name, age)
{
WaterType = waterType;
}
public override void MakeSound()
{
Console.WriteLine($"{Name} makes bubble sounds...");
}
public override void Move()
{
Console.WriteLine($"{Name} swims in {WaterType} water");
}
}
// برنامه اصلی
class Program
{
static void Main()
{
Animal[] animals = new Animal[3];
animals[0] = new Dog("Rex", 3, "German Shepherd");
animals[1] = new Bird("Tweety", 1, 0.25);
animals[2] = new Fish("Nemo", 2, "Salt");
foreach (Animal animal in animals)
{
animal.ShowInfo();
Console.WriteLine();
}
Console.WriteLine("Press Enter to exit...");
Console.ReadLine();
}
}
---
✅ تمرین نهایی درس نهم
سیستمی برای محاسبه حقوق کارمندان طراحی کنید:
1. کلاس abstract Employee با:
· فیلدهای: Name, ID, BaseSalary
· متد abstract CalculateSalary()
2. کلاس Manager : Employee
· Bonus اضافی
· حقوق = BaseSalary + Bonus
3. کلاس SalesPerson : Employee
· Commission (درصد فروش)
· حقوق = BaseSalary + (Sales * Commission / 100)
4. چندریختی: لیستی از Employee بسازید و حقوق همه را محاسبه کنید
csharp
abstract class Employee
{
public string Name { get; set; }
public int ID { get; set; }
public double BaseSalary { get; set; }
public Employee(string name, int id, double baseSalary)
{
Name = name;
ID = id;
BaseSalary = baseSalary;
}
public abstract double CalculateSalary();
public void ShowInfo()
{
Console.WriteLine($"{Name} (ID: {ID})");
Console.WriteLine($"Base Salary: {BaseSalary:C}");
Console.WriteLine($"Total Salary: {CalculateSalary():C}");
}
}
class Manager : Employee
{
public double Bonus { get; set; }
public Manager(string name, int id, double baseSalary, double bonus)
: base(name, id, baseSalary)
{
Bonus = bonus;
}
public override double CalculateSalary()
{
return BaseSalary + Bonus;
}
}
class SalesPerson : Employee
{
public double SalesAmount { get; set; }
public double CommissionPercent { get; set; }
public SalesPerson(string name, int id, double baseSalary, double sales, double commission)
: base(name, id, baseSalary)
{
SalesAmount = sales;
CommissionPercent = commission;
}
public override double CalculateSalary()
{
return BaseSalary + (SalesAmount * CommissionPercent / 100);
}
}
// برنامه اصلی
class Program
{
static void Main()
{
Employee[] employees = new Employee[3];
employees[0] = new Manager("Ali Mohammadi", 101, 8000000, 2000000);
employees[1] = new SalesPerson("Sara Ahmadi", 102, 5000000, 10000000, 5);
employees[2] = new Manager("Reza Karimi", 103, 9000000, 3000000);
foreach (Employee emp in employees)
{
emp.ShowInfo();
Console.WriteLine();
}
Console.WriteLine("Press Enter to exit...");
Console.ReadLine();
}
}
`--- 📌 جمعبندی درس نهم مفهوم کلیدواژه توضیح ارثبری : class Dog : Animal دسترسی به پدر base base.Method() متد قابل بازنویسی virtual public virtual void Method() بازنویسی متد override public override void Method() کلاس چکیده abstract abstract class MyClass متد چکیده abstract public abstract void Method(); غیرقابل ارثبری sealed sealed class MyClass --- 🧪 تمرین برای شما 1. کلاس Shape abstract بسازید با متدهای GetArea() و GetPerimeter() 2. کلاسهای Square، Triangle، Circle را بسازید 3. آرایهای از Shape بسازید و مساحت همه را محاسبه کنید --- اگر این درس را کامل فهمیدید، بگویید تا درس دهم (اینترفیسها) را شروع کنیم. سوالی بود بپرسید.
خیلی خوب، رسیدیم به درس دهم: اینترفیسها (Interface).
اینترفیس یکی از قدرتمندترین مفاهیم در سیشارپ است که به شما اجازه میدهد قراردادهای مشخصی بین کلاسها تعریف کنید.
یک پروژه جدید بسازید (dotnet new console) و کدها را همراه من بنویسید و اجرا کنید.
---
📘 درس دهم – اینترفیسها (Interface)
🎯 سرفصلها:
1. اینترفیس چیست؟
2. تفاوت اینترفیس با کلاس abstract
3. پیادهسازی اینترفیس
4. چندین اینترفیس در یک کلاس
5. اینترفیس به عنوان نوع داده
6. متدهای پیشفرض در اینترفیس (C# 8.0)
7. تمرین جامع
---
⏱️ قسمت 1: اینترفیس چیست؟
اینترفیس = یک قرارداد (Contract) که مشخص میکند کلاس چه کارهایی باید انجام دهد، اما نه چگونگی انجام آن.
csharp
// تعریف اینترفیس
interface IAnimal
{
void MakeSound(); // فقط تعریف، بدون بدنه
void Move();
}
// پیادهسازی اینترفیس در کلاس
class Dog : IAnimal
{
public void MakeSound()
{
Console.WriteLine("Woof! Woof!");
}
public void Move()
{
Console.WriteLine("Dog is running");
}
}
class Cat : IAnimal
{
public void MakeSound()
{
Console.WriteLine("Meow! Meow!");
}
public void Move()
{
Console.WriteLine("Cat is walking silently");
}
}
// استفاده
IAnimal myDog = new Dog();
IAnimal myCat = new Cat();
myDog.MakeSound(); // Woof! Woof!
myCat.MakeSound(); // Meow! Meow!
📌 قوانین اینترفیس:
· فقط امضای متدها را تعریف میکند (بدون بدنه)
· نمیتواند فیلد داشته باشد
· کلاس میتواند چندین اینترفیس را پیادهسازی کند
· همه متدهای اینترفیس باید در کلاس پیادهسازی شوند
---
⏱️ قسمت 2: تفاوت اینترفیس با کلاس abstract
ویژگی اینترفیس (Interface) کلاس Abstract
تعداد در ارثبری چندین تا فقط یک کلاس
بدنه متدها ندارد (قبلاً) میتواند داشته باشد
فیلدها ندارد میتواند داشته باشد
سازنده ندارد میتواند داشته باشد
سطح دسترسی implicit public هر سطحی
کاربرد قرارداد پایه مشترک با بعضی پیادهسازیها
csharp
// اینترفیس: فقط قرارداد
interface IPrinter
{
void Print();
}
// کلاس abstract: میتواند پیادهسازی داشته باشد
abstract class Animal
{
public string Name { get; set; } // فیلد دارد
public abstract void MakeSound(); // بدون پیادهسازی
public void Sleep() // با پیادهسازی
{
Console.WriteLine("Sleeping...");
}
}
---
⏱️ قسمت 3: نامگذاری اینترفیسها
قاعده طلایی: نام اینترفیسها با I بزرگ شروع میشود.
csharp
interface IRepository // ✅ درست
interface ILogger // ✅ درست
interface IConvertible // ✅ درست
interface Printable // ❌ (بدون I)
interface IPrintable // ✅
---
⏱️ قسمت 4: پیادهسازی چندین اینترفیس
یک کلاس میتواند چندین اینترفیس را پیادهسازی کند.
csharp
interface IMovable
{
void Move();
}
interface ISpeakable
{
void Speak();
}
interface IFlyable
{
void Fly();
}
// کلاس میتواند چند اینترفیس داشته باشد
class Bird : IMovable, ISpeakable, IFlyable
{
public void Move()
{
Console.WriteLine("Bird is moving");
}
public void Speak()
{
Console.WriteLine("Bird is chirping");
}
public void Fly()
{
Console.WriteLine("Bird is flying");
}
}
// استفاده
Bird bird = new Bird();
bird.Move();
bird.Speak();
bird.Fly();
---
⏱️ قسمت 5: اینترفیس به عنوان نوع داده
میتوانیم از اینترفیس به عنوان نوع متغیر استفاده کنیم.
`csharp interface IShape { double GetArea(); double GetPerimeter(); } class Circle : IShape { public double Radius { get; set; } public Circle(double radius) { Radius = radius; } public double GetArea() { return Math.PI * Radius * Radius; } public double GetPerimeter() { return 2 * Math.PI * Radius; } } class Rectangle : IShape { public double Width { get; set; } public double Height { get; set; } public Rectangle(double width, double height) { Width = width; Height = height; } public double GetArea() { return Width * Height; } public double GetPerimeter() { return 2 * (Width + Height); } }
// چندریختی با اینترفیس
IShape[] shapes = new IShape[3];
shapes[0] = new Circle(5);
shapes[1] = new Rectangle(4, 6);
shapes[2] = new Circle(3);
foreach (IShape shape in shapes)
{
Console.WriteLine($"Area: {shape.GetArea():F2}");
Console.WriteLine($"Perimeter: {shape.GetPerimeter():F2}");
Console.WriteLine();
}
---
⏱️ قسمت 6: مثال واقعی – سیستم پرداخت
csharp
// اینترفیس پرداخت
interface IPayment
{
void Pay(decimal amount);
string GetPaymentMethod();
}
// پیادهسازی با کارت اعتباری
class CreditCardPayment : IPayment
{
public string CardNumber { get; set; }
public CreditCardPayment(string cardNumber)
{
CardNumber = cardNumber;
}
public void Pay(decimal amount)
{
Console.WriteLine($"Paid {amount:C} using Credit Card ending with {CardNumber.Substring(CardNumber.Length - 4)}");
}
public string GetPaymentMethod()
{
return "Credit Card";
}
}
// پیادهسازی با پیپال
class PayPalPayment : IPayment
{
public string Email { get; set; }
public PayPalPayment(string email)
{
Email = email;
}
public void Pay(decimal amount)
{
Console.WriteLine($"Paid {amount:C} using PayPal account {Email}");
}
public string GetPaymentMethod()
{
return "PayPal";
}
}
// پیادهسازی با ارز دیجیتال
class CryptoPayment : IPayment
{
public string WalletAddress { get; set; }
public CryptoPayment(string walletAddress)
{
WalletAddress = walletAddress;
}
public void Pay(decimal amount)
{
Console.WriteLine($"Paid {amount:C} using Crypto wallet {WalletAddress.Substring(0, 6)}...");
}
public string GetPaymentMethod()
{
return "Cryptocurrency";
}
}
// سیستم پرداخت
class PaymentProcessor
{
public void ProcessPayment(IPayment payment, decimal amount)
{
Console.WriteLine($"Processing {payment.GetPaymentMethod()} payment...");
payment.Pay(amount);
Console.WriteLine("Payment completed!");
}
}
// استفاده
PaymentProcessor processor = new PaymentProcessor();
IPayment payment1 = new CreditCardPayment("1234-5678-9012-3456");
IPayment payment2 = new PayPalPayment("user@example.com");
IPayment payment3 = new CryptoPayment("1A2B3C4D5E6F");
processor.ProcessPayment(payment1, 150.50m);
Console.WriteLine();
processor.ProcessPayment(payment2, 75.25m);
Console.WriteLine();
processor.ProcessPayment(payment3, 200.00m);
---
⏱️ قسمت 7: متدهای پیشفرض در اینترفیس (C# 8.0+)
از C# 8.0 به بعد، میتوان در اینترفیس متد با بدنه (پیشفرض) داشت.
csharp
interface ILogger
{
void Log(string message); // باید پیادهسازی شود
// متد پیشفرض (اختیاری برای پیادهسازی)
void LogError(string error)
{
Console.WriteLine($"ERROR: {error}");
Log(error); // میتواند متد دیگر را صدا بزند
}
}
class FileLogger : ILogger
{
public void Log(string message)
{
Console.WriteLine($"Writing to file: {message}");
}
// نیازی به پیادهسازی LogError نیست (پیشفرض دارد)
}
class ConsoleLogger : ILogger
{
public void Log(string message)
{
Console.WriteLine($"Console: {message}");
}
// میتوان LogError را بازنویسی کرد
public void LogError(string error)
{
Console.WriteLine($"!!! CONSOLE ERROR: {error} !!!");
}
}
// استفاده
ILogger fileLog = new FileLogger();
ILogger consoleLog = new ConsoleLogger();
fileLog.LogError("File not found"); // از پیشفرض استفاده میکند
consoleLog.LogError("Network error"); // از پیادهسازی خودش استفاده میکند
---
✅ تمرین نهایی درس دهم
سیستم مدیریت کاربران با اینترفیس بسازید:
1. اینترفیس IUser با متدهای:
· string GetUsername()
· string GetRole()
· bool HasPermission(string permission)
2. کلاس Admin : IUser
3. کلاس RegularUser : IUser
4. کلاس Guest : IUser
csharp
using System;
using System.Collections.Generic;
interface IUser
{
string GetUsername();
string GetRole();
bool HasPermission(string permission);
}
class Admin : IUser
{
private string username;
public Admin(string name)
{
username = name;
}
public string GetUsername()
{
return username;
}
public string GetRole()
{
return "Administrator";
}
public bool HasPermission(string permission)
{
// ادمین به همه چیز دسترسی دارد
return true;
}
}
class RegularUser : IUser
{
private string username;
private List<string> permissions;
public RegularUser(string name)
{
username = name;
permissions = new List<string> { "read", "write_own" };
}
public string GetUsername()
{
return username;
}
public string GetRole()
{
return "Regular User";
}
public bool HasPermission(string permission)
{
return permissions.Contains(permission);
}
}
class Guest : IUser
{
public string GetUsername()
{
return "Guest";
}
public string GetRole()
{
return "Guest";
}
public bool HasPermission(string permission)
{
// مهمان فقط خواندن دارد
return permission == "read";
}
}
// سیستم مدیریت دسترسی
class AccessManager
{
public void CheckAccess(IUser user, string permission)
{
Console.WriteLine($"User: {user.GetUsername()} (Role: {user.GetRole()})");
Console.WriteLine($"Requested permission: {permission}");
if (user.HasPermission(permission))
{
Console.WriteLine("✅ ACCESS GRANTED");
}
else
{
Console.WriteLine("❌ ACCESS DENIED");
}
Console.WriteLine();
}
}
// برنامه اصلی
class Program
{
static void Main()
{
AccessManager manager = new AccessManager();
IUser[] users = new IUser[3];
users[0] = new Admin("Ali_Admin");
users[1] = new RegularUser("Sara_User");
users[2] = new Guest();
string[] permissions = { "read", "write", "delete", "write_own" };
foreach (IUser user in users)
{
Console.WriteLine($"=== Testing {user.GetUsername()} ===");
foreach (string perm in permissions)
{
manager.CheckAccess(user, perm);
}
}
Console.WriteLine("Press Enter to exit...");
Console.ReadLine();
}
}
`--- 📌 جمعبندی درس دهم مفهوم توضیح اینترفیس قراردادی که کلاس باید پیادهسازی کند نامگذاری با I شروع میشود (مثل IMovable) پیادهسازی کلاس : اینترفیس چند اینترفیس class MyClass : I1, I2, I3 متدهای پیشفرض از C# 8.0 به بعد میتوان بدنه داشت اینترفیس در مقابل کلاس Abstract: سناریو راه حل میخواهم چندین کلاس از یک پایه ارث ببرند کلاس Abstract میخواهم یک قرارداد مشخص کنم اینترفیس میخواهم یک کلاس چند نوع رفتار داشته باشد چندین اینترفیس میخواهم فیلد داشته باشم کلاس Abstract --- 🧪 تمرین برای شما 1. اینترفیس ICalculator بسازید با متدهای Add, Subtract, Multiply, Divide 2. دو کلاس BasicCalculator و ScientificCalculator آن را پیادهسازی کنند 3. اینترفیس IComparable را در کلاس Student پیادهسازی کنید و دانشجوها را بر اساس نمره مرتب کنید --- تبریک! 🎉 شما 10 درس اصلی سیشارپ را کامل کردید. درسهای پیشنهادی برای ادامه: · دهم: Delegates و Events · یازدهم: LINQ · دوازدهم: Exception Handling پیشرفته · سیزدهم: کار با فایلها · چهاردهم: Async/Await اگر سوالی دارید یا میخواهید درس بعدی را شروع کنید، بگویید. موفق باشید!
خیلی خوب، رسیدیم به درس یازدهم: کلاسهای استاتیک (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()); // #FF0000
Console.WriteLine(red.GetName()); // Red
Console.WriteLine(custom.GetHexCode()); // #80C832
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) را شروع کنیم. سوالی بود بپرسید.