أمثلة في لغة السي شارب
لغة السي شارب (C#) هي لغة برمجة حديثة ومتعددة الأغراض طورتها شركة مايكروسوفت كجزء من إطار العمل .NET. تتميز هذه اللغة بكونها قوية وسهلة التعلم، مما يجعلها خيارًا شائعًا بين المطورين لبناء تطبيقات متنوعة مثل تطبيقات الويب، تطبيقات سطح المكتب، تطبيقات الهواتف المحمولة، وألعاب الفيديو. في هذا المقال سنتناول أمثلة شاملة ومتنوعة توضح كيفية استخدام لغة السي شارب في مختلف الجوانب البرمجية مع شرح مفصل لكل جزء من الكود لضمان فهم عميق للمفاهيم الأساسية والمتقدمة.
لنبدأ بمفهوم المتغيرات وأنواع البيانات في السي شارب. المتغيرات هي الحاويات التي نستخدمها لتخزين البيانات، ولكل متغير نوع معين يحدد نوع البيانات التي يمكنه تخزينها. على سبيل المثال، يمكننا تعريف متغير لتخزين عدد صحيح كالتالي:
int number = 10;
في هذا المثال، int
هو نوع البيانات الذي يمثل الأعداد الصحيحة، وnumber
هو اسم المتغير الذي يحمل القيمة 10
. بالإضافة إلى int
، هناك أنواع بيانات أخرى مثل double
للأعداد العشرية، char
للحروف الفردية، وstring
للسلاسل النصية. على سبيل المثال:
double pi = 3.14159;
char letter = 'A';
string greeting = "Hello, World!";
بعد فهم المتغيرات وأنواع البيانات، ننتقل إلى التحكم في تدفق البرنامج باستخدام الشروط والحلقات. يمكن استخدام تعبيرات شرطية مثل if
وelse
لتنفيذ كتل من الكود بناءً على تحقق شرط معين. على سبيل المثال:
int age = 20;
if (age >= 18)
{
Console.WriteLine("You are an adult.");
}
else
{
Console.WriteLine("You are a minor.");
}
في هذا المثال، يتحقق البرنامج مما إذا كانت قيمة age
أكبر من أو تساوي 18، وإذا كان الشرط صحيحًا، يطبع رسالة تفيد بأن المستخدم بالغ، وإلا يطبع رسالة تفيد بأنه قاصر.
أما بالنسبة للحلقات، فهي تُستخدم لتكرار تنفيذ كتل من الكود حتى يتحقق شرط معين. على سبيل المثال، يمكن استخدام حلقة for
لطباعة الأرقام من 1 إلى 5:
for (int i = 1; i <= 5; i++)
{
Console.WriteLine(i);
}
هذا الكود يبدأ بقيمة i
تساوي 1 ويستمر في زيادة i
بمقدار 1 في كل دورة حتى تصل إلى 5، مطبوعًا كل قيمة على حدة.
بالإضافة إلى الشروط والحلقات، تعتبر الدوال (Functions) من الأساسيات الهامة في البرمجة بلغة السي شارب. الدوال تسمح بتقسيم البرنامج إلى وحدات صغيرة قابلة لإعادة الاستخدام، مما يسهل صيانة الكود وفهمه. على سبيل المثال، يمكن تعريف دالة لحساب مجموع رقمين كالتالي:
int Add(int a, int b)
{
return a + b;
}
int result = Add(5, 3);
Console.WriteLine(result); // يطبع 8
في هذا المثال، دالة Add
تأخذ متغيرين من النوع int
وتعيد ناتج جمعهما. يتم استدعاء الدالة مع القيم 5 و3، وتخزين النتيجة في المتغير result
ثم طباعتها.
البرمجة الكائنية (Object-Oriented Programming) هي واحدة من أهم ميزات السي شارب، حيث تسمح بتنظيم الكود بطريقة تعكس الكائنات الحقيقية وعلاقاتها. يتم تعريف الكائنات باستخدام الفئات (Classes) التي تحدد خصائص وسلوكيات الكائنات. على سبيل المثال، يمكن تعريف فئة Person
تحتوي على خصائص مثل Name
وAge
وسلوك مثل Greet
:
public class Person
{
public string Name { get; set; }
public int Age { get; set; }
public void Greet()
{
Console.WriteLine($"Hello, my name is {Name} and I am {Age} years old.");
}
}
Person person = new Person();
person.Name = "Alice";
person.Age = 30;
person.Greet(); // يطبع: Hello, my name is Alice and I am 30 years old.
في هذا المثال، نعرف فئة Person
بخصائص Name
وAge
، ودالة Greet
التي تطبع رسالة ترحيب تحتوي على اسم وعمر الشخص. بعد ذلك، ننشئ كائنًا من الفئة Person
، نعطيه قيمًا للخصائص، ونستدعي الدالة Greet
لعرض الرسالة.
التوريث (Inheritance) هو مفهوم آخر في البرمجة الكائنية يسمح للفئات بالاستفادة من خصائص وسلوكيات فئات أخرى. على سبيل المثال، يمكن تعريف فئة Student
التي ترث من فئة Person
وتضيف خصائص وسلوكيات إضافية:
public class Student : Person
{
public string School { get; set; }
public void Study()
{
Console.WriteLine($"{Name} is studying at {School}.");
}
}
Student student = new Student();
student.Name = "Bob";
student.Age = 20;
student.School = "University";
student.Greet(); // يطبع: Hello, my name is Bob and I am 20 years old.
student.Study(); // يطبع: Bob is studying at University.
هنا، فئة Student
ترث من Person
وتضيف خاصية School
ودالة Study
، مما يتيح للكائنات من فئة Student
استخدام كل من خصائص وسلوكيات فئة Person
بالإضافة إلى تلك المضافة في Student
.
التعددية الشكلية (Polymorphism) هي ميزة تسمح باستخدام كائنات من فئات مختلفة من خلال واجهة مشتركة، مما يزيد من مرونة الكود وقابليته لإعادة الاستخدام. على سبيل المثال، يمكن تعريف دالة تقبل كائنًا من فئة Person
وتستدعي دالة Greet
بغض النظر عن نوع الكائن الحقيقي:
public void Introduce(Person person)
{
person.Greet();
}
Person person = new Person { Name = "Charlie", Age = 25 };
Student student = new Student { Name = "Diana", Age = 22, School = "College" };
Introduce(person); // يطبع: Hello, my name is Charlie and I am 25 years old.
Introduce(student); // يطبع: Hello, my name is Diana and I am 22 years old.
في هذا المثال، دالة Introduce
تقبل كائنًا من نوع Person
وتستدعي دالة Greet
. عند تمرير كائن من فئة Student
، يتم استخدام دالة Greet
المعرفة في فئة Person
، مما يعكس مفهوم التعددية الشكلية.
الواجهات (Interfaces) هي عقود تحدد مجموعة من الدوال التي يجب على الفئات التي تنفذها أن توفرها، دون تحديد كيفية تنفيذها. هذا يعزز من مرونة التصميم ويدعم البرمجة التعاقدية. على سبيل المثال، يمكن تعريف واجهة IMovable
تحتوي على دالة Move
:
public interface IMovable
{
void Move();
}
public class Car : IMovable
{
public void Move()
{
Console.WriteLine("The car is moving.");
}
}
public class Bird : IMovable
{
public void Move()
{
Console.WriteLine("The bird is flying.");
}
}
IMovable car = new Car();
IMovable bird = new Bird();
car.Move(); // يطبع: The car is moving.
bird.Move(); // يطبع: The bird is flying.
في هذا المثال، كل من Car
وBird
تنفذان واجهة IMovable
وتوفران تنفيذًا مختلفًا لدالة Move
, مما يتيح التعامل مع كائنات من أنواع مختلفة من خلال نفس الواجهة.
الاستثناءات (Exceptions) هي آلية لمعالجة الأخطاء التي قد تحدث أثناء تنفيذ البرنامج. يتم استخدام كتل try-catch
للتعامل مع هذه الأخطاء بشكل منظم ومنع انهيار البرنامج. على سبيل المثال:
try
{
int[] numbers = { 1, 2, 3 };
Console.WriteLine(numbers[5]);
}
catch (IndexOutOfRangeException ex)
{
Console.WriteLine("An error occurred: " + ex.Message);
}
في هذا المثال، نحاول الوصول إلى عنصر غير موجود في مصفوفة numbers
، مما يؤدي إلى رفع استثناء من نوع IndexOutOfRangeException
. يتم التقاط هذا الاستثناء في كتلة catch
ويتم طباعة رسالة توضح الخطأ بدلاً من توقف البرنامج بشكل غير متوقع.
البرمجة غير المتزامنة (Asynchronous Programming) تعد من الميزات المتقدمة في السي شارب، حيث تسمح بتنفيذ عمليات تستغرق وقتًا طويلًا دون تجميد واجهة المستخدم أو توقف التطبيق عن الاستجابة. يتم ذلك باستخدام الكلمات المفتاحية async
وawait
. على سبيل المثال، يمكن تحميل بيانات من الإنترنت بشكل غير متزامن:
public async Task<string> FetchDataAsync(string url)
{
using (HttpClient client = new HttpClient())
{
string data = await client.GetStringAsync(url);
return data;
}
}
public async void GetData()
{
string result = await FetchDataAsync("https://example.com");
Console.WriteLine(result);
}
في هذا المثال، دالة FetchDataAsync
تقوم بتحميل بيانات من عنوان URL معين بشكل غير متزامن، مما يسمح للتطبيق بالاستمرار في تنفيذ أوامر أخرى أثناء انتظار استجابة الخادم. عند استدعاء دالة GetData
, يتم الانتظار حتى تكتمل عملية التحميل ومن ثم طباعة النتيجة.
التحكم في الوصول (Access Modifiers) يسمح بتحديد مستوى الوصول إلى الأعضاء داخل الفئات، مما يعزز من أمان الكود وتنظيمه. من بين معدلات الوصول الشائعة: public
, private
, protected
, وinternal
. على سبيل المثال:
public class BankAccount
{
private double balance;
public void Deposit(double amount)
{
if (amount > 0)
{
balance += amount;
Console.WriteLine($"Deposited: {amount}, New Balance: {balance}");
}
}
public void Withdraw(double amount)
{
if (amount > 0 && amount <= balance)
{
balance -= amount;
Console.WriteLine($"Withdrew: {amount}, New Balance: {balance}");
}
else
{
Console.WriteLine("Invalid withdrawal amount.");
}
}
}
BankAccount account = new BankAccount();
account.Deposit(500);
account.Withdraw(200);
// account.balance = 1000; // هذا السطر سيسبب خطأ لأنه لا يمكن الوصول إلى balance مباشرة
في هذا المثال، الخاصية balance
معرفة كمجموعة private
، مما يمنع الوصول إليها مباشرة من خارج الفئة. بدلاً من ذلك، يتم توفير دوال Deposit
وWithdraw
للتحكم في التفاعل مع الرصيد، مما يضمن سلامة البيانات وعدم التلاعب غير المشروع بها.
التحويل بين الأنواع (Type Conversion) يعد جزءًا أساسيًا من البرمجة، حيث قد نحتاج إلى تحويل أنواع بيانات مختلفة لتناسب العمليات المطلوبة. في السي شارب، يمكن القيام بالتحويل الضمني أو الصريح. على سبيل المثال:
// تحويل ضمني من int إلى double
int integer = 10;
double dbl = integer;
Console.WriteLine(dbl); // يطبع 10
// تحويل صريح من double إلى int
double pi = 3.14;
int truncatedPi = (int)pi;
Console.WriteLine(truncatedPi); // يطبع 3
في هذا المثال، التحويل من int
إلى double
يتم بشكل ضمني لأنه لا يفقد أي بيانات، بينما التحويل من double
إلى int
يتطلب تحويلًا صريحًا لأن ذلك يمكن أن يؤدي إلى فقدان البيانات العشرية.
العمل مع المجموعات (Collections) هو جزء مهم من البرمجة، حيث نحتاج إلى تخزين ومعالجة مجموعات من العناصر بطرق فعالة. تقدم السي شارب مكتبات قوية للتعامل مع المجموعات مثل List
, Dictionary
, وHashSet
. على سبيل المثال، يمكن استخدام قائمة لتخزين مجموعة من الأسماء:
List<string> names = new List<string>();
names.Add("Alice");
names.Add("Bob");
names.Add("Charlie");
foreach (string name in names)
{
Console.WriteLine(name);
}
في هذا المثال، نستخدم فئة List<string>
لتخزين قائمة من الأسماء، ثم نستخدم حلقة foreach
لطباعة كل اسم على حدة. المجموعات تتيح لنا إضافة، إزالة، والبحث عن العناصر بكفاءة عالية.
إدارة الذاكرة في السي شارب تتم بشكل تلقائي باستخدام جامع القمامة (Garbage Collector) الذي يتولى تحرير الذاكرة المستخدمة من قبل الكائنات التي لم تعد قيد الاستخدام. ومع ذلك، يمكن للمطورين تحسين استخدام الذاكرة من خلال فهم كيفية إنشاء وإدارة الكائنات بشكل فعال، وتجنب التسريبات الذاكرية (Memory Leaks) عبر التخلص من الموارد غير المدارة بشكل صحيح باستخدام واجهة IDisposable
والدالة Dispose
.
البرمجة الوظيفية (Functional Programming) بدأت تظهر في السي شارب بإصدارات حديثة، حيث يمكن استخدام الدوال اللامبدية (Lambda Expressions) والوظائف عالية الترتيب (Higher-Order Functions) لتعزيز كتابة الكود بطريقة أكثر تعبيرية وقابلة للصيانة. على سبيل المثال، يمكن استخدام دالة Select
من LINQ لتحويل قائمة من الأعداد إلى مربعاتها:
List<int> numbers = new List<int> { 1, 2, 3, 4, 5 };
List<int> squares = numbers.Select(x => x * x).ToList();
foreach (int square in squares)
{
Console.WriteLine(square);
}
في هذا المثال، نستخدم تعبير لامبدي x => x * x
لتحويل كل عدد في القائمة إلى مربعه، مما يجعل الكود أكثر اختصارًا ووضوحًا.
التعامل مع الملفات (File Handling) هو جانب آخر مهم في البرمجة، حيث قد نحتاج إلى قراءة أو كتابة البيانات من وإلى الملفات. في السي شارب، يمكن استخدام فئة File
من مكتبة System.IO
للقيام بذلك. على سبيل المثال، لقراءة محتويات ملف نصي:
string filePath = "data.txt";
if (File.Exists(filePath))
{
string content = File.ReadAllText(filePath);
Console.WriteLine(content);
}
else
{
Console.WriteLine("File does not exist.");
}
وفي حالة كتابة بيانات إلى ملف:
string[] lines = { "First line", "Second line", "Third line" };
File.WriteAllLines("output.txt", lines);
Console.WriteLine("Data written to output.txt");
في هذا المثال، نتحقق أولاً من وجود الملف قبل محاولة قراءته، ثم نقرأ محتوياته ونطبعه. وفي الجزء الثاني، نكتب مجموعة من السطور إلى ملف جديد أو نعيد كتابة ملف موجود.
الاختبارات (Testing) تعتبر جزءًا حيويًا من عملية تطوير البرمجيات لضمان جودة الكود وسلامته. يمكن استخدام أطر العمل مثل NUnit
أو xUnit
لكتابة اختبارات وحدات (Unit Tests) في السي شارب. على سبيل المثال، يمكن كتابة اختبار لدالة Add
التي ناقشناها سابقًا:
using NUnit.Framework;
[TestFixture]
public class MathTests
{
[Test]
public void Add_TwoPositiveNumbers_ReturnsCorrectSum()
{
int a = 5;
int b = 3;
int expected = 8;
int result = Add(a, b);
Assert.AreEqual(expected, result);
}
public int Add(int a, int b)
{
return a + b;
}
}
في هذا المثال، نستخدم إطار عمل NUnit
لتعريف فئة اختبار تحتوي على دالة اختبار تتحقق من أن دالة Add
تعيد الناتج الصحيح عند تمرير عددين إيجابيين.
التوثيق (Documentation) هو جانب مهم لضمان أن الكود قابل للفهم والصيانة من قبل الآخرين أو من قبل نفسك في المستقبل. يمكن استخدام تعليقات XML في السي شارب لإنشاء توثيق تلقائي يساعد المطورين على فهم وظيفة الدوال والفئات بسهولة. على سبيل المثال:
/// <summary>
/// Calculates the sum of two integers.
/// </summary>
/// <param name="a">The first integer.</param>
/// <param name="b">The second integer.</param>
/// <returns>The sum of a and b.</returns>
public int Add(int a, int b)
{
return a + b;
}
هذه التعليقات توفر وصفًا واضحًا لدالة Add
، مما يسهل على المطورين الآخرين فهم كيفية استخدامها وما تقوم به دون الحاجة إلى قراءة تفاصيل التنفيذ.
المفوضات والأحداث (Delegates and Events)
تعد المفوضات (Delegates) والأحداث (Events) من العناصر الأساسية في لغة السي شارب التي تدعم البرمجة التفاعلية والتعامل مع الأحداث بطريقة منظمة. المفوضات هي أنواع خاصة من المؤشرات على الدوال، مما يتيح تخزين واستدعاء دوال معينة في وقت لاحق. أما الأحداث فهي تعتمد على المفوضات لتنبيه الأجزاء المختلفة من التطبيق بحدوث تغييرات أو إجراءات معينة.
المفوضات (Delegates)
المفوضات تُمكن المطورين من تمرير الدوال كمعاملات إلى دوال أخرى، مما يعزز من مرونة الكود وقابليته لإعادة الاستخدام. يمكن تعريف مفوضة على النحو التالي:
// تعريف مفوضة تقوم بإرجاع قيمة من نوع int وتأخذ معاملين من نوع int
public delegate int MathOperation(int a, int b);
// دوال تتوافق مع توقيع المفوضة MathOperation
public int Add(int x, int y)
{
return x + y;
}
public int Multiply(int x, int y)
{
return x * y;
}
// استخدام المفوضة
MathOperation operation = Add;
int result = operation(5, 3); // يطبع 8
operation = Multiply;
result = operation(5, 3); // يطبع 15
في هذا المثال، قمنا بتعريف مفوضة MathOperation
التي تأخذ معاملين من نوع int
وتُعيد نتيجة من نفس النوع. بعد ذلك، قمنا بتعريف دوال Add
وMultiply
التي تتوافق مع توقيع المفوضة. يمكننا تعيين دوال مختلفة إلى المفوضة واستدعائها بشكل ديناميكي.
الأحداث (Events)
الأحداث تُستخدم للتفاعل بين الكائنات، حيث يمكن للكائن إشعار كائنات أخرى بحدوث تغييرات أو إجراءات معينة. تُعرف الأحداث باستخدام المفوضات، وغالبًا ما تُستخدم في واجهات المستخدم والتطبيقات التفاعلية.
// تعريف مفوضة للأحداث
public delegate void Notify(string message);
// تعريف فئة تقوم بإطلاق حدث
public class Process
{
public event Notify ProcessCompleted;
public void StartProcess()
{
Console.WriteLine("Process started.");
// تنفيذ بعض العمليات
System.Threading.Thread.Sleep(2000); // محاكاة عملية تستغرق وقتًا
OnProcessCompleted("Process completed successfully.");
}
protected virtual void OnProcessCompleted(string message)
{
ProcessCompleted?.Invoke(message);
}
}
// استخدام الأحداث
public class Program
{
public static void Main(string[] args)
{
Process process = new Process();
process.ProcessCompleted += Process_ProcessCompleted;
process.StartProcess();
}
private static void Process_ProcessCompleted(string message)
{
Console.WriteLine(message);
}
}
في هذا المثال، قمنا بتعريف مفوضة Notify
والتي تُستخدم لتعريف الحدث ProcessCompleted
داخل فئة Process
. عند اكتمال العملية، يتم إطلاق الحدث وإعلام جميع المشتركين به. في البرنامج الرئيسي، نقوم بالاشتراك في الحدث وتحديد الدالة التي ستتعامل مع الإشعار عند حدوثه.
الأجيال (Generics)
تُعتبر الأجيال (Generics) ميزة قوية في السي شارب تسمح بإنشاء فئات ودوال قابلة لإعادة الاستخدام تعمل مع أنواع بيانات مختلفة دون الحاجة إلى تكرار الكود. تساعد الأجيال في تحسين الأمان النوعي (Type Safety) والأداء عن طريق تقليل الحاجة إلى التحويلات الصريحة للأنواع.
مثال على استخدام الأجيال في الفئات
// تعريف فئة عامة (Generic Class)
public class GenericBox<T>
{
private T _item;
public void Add(T item)
{
_item = item;
}
public T GetItem()
{
return _item;
}
}
// استخدام الفئة العامة مع أنواع مختلفة
GenericBox<int> intBox = new GenericBox<int>();
intBox.Add(123);
Console.WriteLine(intBox.GetItem()); // يطبع 123
GenericBox<string> strBox = new GenericBox<string>();
strBox.Add("Hello Generics");
Console.WriteLine(strBox.GetItem()); // يطبع "Hello Generics"
في هذا المثال، قمنا بتعريف فئة GenericBox
التي تستقبل نوعًا عامًا T
. يمكننا إنشاء كائنات من هذه الفئة بأنواع مختلفة مثل int
وstring
دون الحاجة إلى تعريف فئات منفصلة لكل نوع.
مثال على استخدام الأجيال في الدوال
// تعريف دالة عامة (Generic Method)
public void Swap<T>(ref T a, ref T b)
{
T temp = a;
a = b;
b = temp;
}
// استخدام الدالة العامة
int x = 5, y = 10;
Swap(ref x, ref y);
Console.WriteLine($"x: {x}, y: {y}"); // يطبع x: 10, y: 5
string first = "Apple", second = "Banana";
Swap(ref first, ref second);
Console.WriteLine($"first: {first}, second: {second}"); // يطبع first: Banana, second: Apple
هنا، قمنا بتعريف دالة Swap
التي تستقبل معاملين من نوع عام T
وتقوم بتبديل قيمهما. يمكن استخدام هذه الدالة مع أي نوع بيانات يدعم التبديل.
الانعكاس (Reflection)
الانعكاس (Reflection) هي تقنية تمكن المطورين من استكشاف معلومات النوع (Type Information) في وقت التشغيل، مثل معرفة خصائص الكائنات، الدوال، والمفوضات. تُستخدم الانعكاس في سيناريوهات مثل إنشاء كائنات ديناميكيًا، التحقق من الأنواع، والتعامل مع التعليقات التوضيحية (Attributes).
مثال على استخدام الانعكاس
using System;
using System.Reflection;
// تعريف فئة مع بعض الخصائص والدوال
public class Person
{
public string Name { get; set; }
public int Age { get; set; }
public void Greet()
{
Console.WriteLine($"Hello, my name is {Name} and I am {Age} years old.");
}
}
public class Program
{
public static void Main(string[] args)
{
Person person = new Person { Name = "Eve", Age = 28 };
Type type = person.GetType();
// استعراض الخصائص
Console.WriteLine("Properties:");
foreach (PropertyInfo prop in type.GetProperties())
{
Console.WriteLine($"{prop.Name} = {prop.GetValue(person)}");
}
// استعراض الدوال
Console.WriteLine("\nMethods:");
foreach (MethodInfo method in type.GetMethods())
{
Console.WriteLine(method.Name);
}
// استدعاء دالة باستخدام الانعكاس
MethodInfo greetMethod = type.GetMethod("Greet");
greetMethod.Invoke(person, null);
}
}
في هذا المثال، نستخدم الانعكاس لاستعراض خصائص ودوال فئة Person
. كما نقوم باستدعاء دالة Greet
ديناميكيًا باستخدام الانعكاس، مما يتيح لنا التحكم في الكائنات بطريقة مرنة وديناميكية.
النمط اللامحدود (Lambda Expressions) والـ LINQ بعمق أكبر
تعتبر تعبيرات اللامدا (Lambda Expressions) جزءًا أساسيًا من البرمجة الوظيفية في السي شارب، وتستخدم بشكل واسع مع لغة الاستعلام المتكاملة (LINQ) لتنفيذ استعلامات قوية ومختصرة على المجموعات والبيانات.
استخدام LINQ مع تعبيرات اللامدا
using System;
using System.Collections.Generic;
using System.Linq;
public class Program
{
public static void Main(string[] args)
{
List<Person> people = new List<Person>
{
new Person { Name = "Alice", Age = 30 },
new Person { Name = "Bob", Age = 25 },
new Person { Name = "Charlie", Age = 35 },
new Person { Name = "Diana", Age = 28 }
};
// استعلام LINQ لاختيار الأشخاص الذين أعمارهم أكبر من 28
var adults = people.Where(p => p.Age > 28);
Console.WriteLine("Adults:");
foreach (var person in adults)
{
Console.WriteLine($"{person.Name}, {person.Age}");
}
// ترتيب الأشخاص حسب العمر
var sortedPeople = people.OrderBy(p => p.Age);
Console.WriteLine("\nSorted People by Age:");
foreach (var person in sortedPeople)
{
Console.WriteLine($"{person.Name}, {person.Age}");
}
// اختيار الأسماء فقط
var names = people.Select(p => p.Name);
Console.WriteLine("\nNames:");
foreach (var name in names)
{
Console.WriteLine(name);
}
// تجميع البيانات
int totalAge = people.Sum(p => p.Age);
Console.WriteLine($"\nTotal Age: {totalAge}");
}
}
public class Person
{
public string Name { get; set; }
public int Age { get; set; }
}
في هذا المثال، نستخدم LINQ لتنفيذ استعلامات مختلفة على قائمة من الكائنات Person
. نستخدم تعبيرات اللامدا لتعريف شروط الاستعلام بطريقة مختصرة وواضحة، مما يسهل قراءة وصيانة الكود.
حقن الاعتماديات (Dependency Injection)
حقن الاعتماديات (Dependency Injection) هو نمط تصميم يهدف إلى تقليل الترابط بين مكونات النظام من خلال تمرير الاعتماديات إلى الكائنات بدلاً من إنشائها داخليًا. يعزز هذا النمط من قابلية الاختبار وإعادة استخدام الكود.
مثال على حقن الاعتماديات باستخدام الإطار المدمج في السي شارب
using System;
using Microsoft.Extensions.DependencyInjection;
// تعريف واجهة لخدمة الترحيب
public interface IGreeter
{
void Greet(string name);
}
// تنفيذ واجهة IGreeter
public class ConsoleGreeter : IGreeter
{
public void Greet(string name)
{
Console.WriteLine($"Hello, {name}!");
}
}
// فئة تستخدم خدمة IGreeter
public class WelcomeService
{
private readonly IGreeter _greeter;
public WelcomeService(IGreeter greeter)
{
_greeter = greeter;
}
public void Welcome(string name)
{
_greeter.Greet(name);
}
}
public class Program
{
public static void Main(string[] args)
{
// إعداد خدمة الحقن
var serviceProvider = new ServiceCollection()
.AddSingleton<IGreeter, ConsoleGreeter>()
.AddTransient<WelcomeService>()
.BuildServiceProvider();
// الحصول على خدمة WelcomeService عبر الحقن
var welcomeService = serviceProvider.GetService<WelcomeService>();
welcomeService.Welcome("Frank");
}
}
في هذا المثال، نستخدم مكتبة Microsoft.Extensions.DependencyInjection
لإعداد نظام حقن الاعتماديات. نعرف واجهة IGreeter
وتنفيذها ConsoleGreeter
. ثم نعرف فئة WelcomeService
التي تعتمد على IGreeter
. عند تشغيل البرنامج، يتم إنشاء كائنات ConsoleGreeter
وWelcomeService
بشكل تلقائي بواسطة نظام الحقن، مما يسهل إدارة الاعتماديات وتقليل الترابط بين المكونات.
إطار العمل Entity Framework
يعد Entity Framework (EF) إطار عمل ORM (Object-Relational Mapping) من مايكروسوفت، يتيح للمطورين العمل مع قواعد البيانات باستخدام كائنات السي شارب بدلاً من كتابة استعلامات SQL مباشرة. يسهل EF عمليات CRUD (إنشاء، قراءة، تحديث، حذف) ويعزز من الإنتاجية وسرعة التطوير.
مثال على استخدام Entity Framework مع قاعدة بيانات بسيطة
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.EntityFrameworkCore;
// تعريف نموذج البيانات
public class Product
{
public int ProductId { get; set; }
public string Name { get; set; }
public double Price { get; set; }
}
// تعريف سياق قاعدة البيانات
public class AppDbContext : DbContext
{
public DbSet<Product> Products { get; set; }
// إعداد الاتصال بقاعدة البيانات
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseInMemoryDatabase("TestDb"); // استخدام قاعدة بيانات في الذاكرة للتبسيط
}
}
public class Program
{
public static void Main(string[] args)
{
using (var context = new AppDbContext())
{
// إضافة منتجات جديدة
var product1 = new Product { Name = "Laptop", Price = 1200.00 };
var product2 = new Product { Name = "Smartphone", Price = 800.00 };
context.Products.AddRange(product1, product2);
context.SaveChanges();
// استعلام عن المنتجات
List<Product> products = context.Products.ToList();
Console.WriteLine("Products:");
foreach (var product in products)
{
Console.WriteLine($"{product.ProductId}: {product.Name} - ${product.Price}");
}
// تحديث منتج
var laptop = context.Products.First(p => p.Name == "Laptop");
laptop.Price = 1100.00;
context.SaveChanges();
// حذف منتج
var smartphone = context.Products.First(p => p.Name == "Smartphone");
context.Products.Remove(smartphone);
context.SaveChanges();
// الاستعلام بعد التحديث والحذف
products = context.Products.ToList();
Console.WriteLine("\nAfter Update and Delete:");
foreach (var product in products)
{
Console.WriteLine($"{product.ProductId}: {product.Name} - ${product.Price}");
}
}
}
}
في هذا المثال، نستخدم Entity Framework
لإنشاء نموذج بيانات Product
وسياق قاعدة البيانات AppDbContext
. نقوم بإضافة منتجات، استعلامها، تحديثها، وحذفها باستخدام EF بدون الحاجة لكتابة استعلامات SQL يدوية. استخدمنا قاعدة بيانات في الذاكرة للتبسيط، ولكن يمكن تكوين EF للعمل مع قواعد بيانات حقيقية مثل SQL Server أو MySQL بسهولة.
تطوير تطبيقات الويب باستخدام ASP.NET Core
تعد ASP.NET Core إطار عمل قوي من مايكروسوفت لبناء تطبيقات الويب والخدمات السحابية. يوفر ASP.NET Core مرونة عالية وأداءً ممتازًا، ويدعم بناء تطبيقات RESTful APIs، تطبيقات MVC، وتطبيقات الويب الحقيقية (Real-time Web Applications).
مثال على إنشاء API بسيط باستخدام ASP.NET Core
- إعداد المشروع:
أولاً، تأكد من تثبيت الـ .NET SDK. ثم، قم بإنشاء مشروع ويب جديد:
dotnet new webapi -n MyApi cd MyApi
- تعريف نموذج البيانات:
// Models/Product.cs public class Product { public int Id { get; set; } public string Name { get; set; } public double Price { get; set; } }
- تعريف سياق قاعدة البيانات باستخدام Entity Framework:
// Data/AppDbContext.cs using Microsoft.EntityFrameworkCore; public class AppDbContext : DbContext { public AppDbContext(DbContextOptions<AppDbContext> options) : base(options) { } public DbSet<Product> Products { get; set; } }
- تكوين الخدمات في
Program.cs
:using Microsoft.EntityFrameworkCore; var builder = WebApplication.CreateBuilder(args);
// إضافة خدمات إلى حاوية الخدمات builder.Services.AddControllers(); builder.Services.AddDbContext(options => options.UseInMemoryDatabase(“ProductsDb”)); builder.Services.AddEndpointsApiExplorer(); builder.Services.AddSwaggerGen();
var app = builder.Build();
// تكوين وسيط التطبيق if (app.Environment.IsDevelopment()) { app.UseSwagger(); app.UseSwaggerUI(); }
app.UseAuthorization();
app.MapControllers();
app.Run();
5. **إنشاء وحدة تحكم (Controller) للتعامل مع الـ API:**
```csharp
// Controllers/ProductsController.cs
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
[Route("api/[controller]")]
[ApiController]
public class ProductsController : ControllerBase
{
private readonly AppDbContext _context;
public ProductsController(AppDbContext context)
{
_context = context;
}
// GET: api/Products
[HttpGet]
public async Task<ActionResult<IEnumerable<Product>>> GetProducts()
{
return await _context.Products.ToListAsync();
}
// GET: api/Products/5
[HttpGet("{id}")]
public async Task<ActionResult<Product>> GetProduct(int id)
{
var product = await _context.Products.FindAsync(id);
if (product == null)
{
return NotFound();
}
return product;
}
// POST: api/Products
[HttpPost]
public async Task<ActionResult<Product>> PostProduct(Product product)
{
_context.Products.Add(product);
await _context.SaveChangesAsync();
return CreatedAtAction(nameof(GetProduct), new { id = product.Id }, product);
}
// PUT: api/Products/5
[HttpPut("{id}")]
public async Task<IActionResult> PutProduct(int id, Product product)
{
if (id != product.Id)
{
return BadRequest();
}
_context.Entry(product).State = EntityState.Modified;
try
{
await _context.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException)
{
if (!_context.Products.Any(e => e.Id == id))
{
return NotFound();
}
else
{
throw;
}
}
return NoContent();
}
// DELETE: api/Products/5
[HttpDelete("{id}")]
public async Task<IActionResult> DeleteProduct(int id)
{
var product = await _context.Products.FindAsync(id);
if (product == null)
{
return NotFound();
}
_context.Products.Remove(product);
await _context.SaveChangesAsync();
return NoContent();
}
}
- تشغيل التطبيق:
استخدم الأمر التالي لتشغيل التطبيق:
dotnet run
بعد تشغيل التطبيق، يمكنك الوصول إلى واجهة Swagger من خلال المتصفح لاختبار الـ API:
https://localhost:<port>/swagger
في هذا المثال، قمنا بإنشاء API بسيط لإدارة المنتجات باستخدام ASP.NET Core وEntity Framework. يمكننا إجراء عمليات CRUD على المنتجات عبر نقاط النهاية (Endpoints) المعرفة في وحدة التحكم ProductsController
.
البرمجة المتوازية (Parallel Programming)
البرمجة المتوازية تسمح بتنفيذ عمليات متعددة في نفس الوقت، مما يحسن من أداء التطبيقات التي تتطلب معالجة كثيفة أو عمليات طويلة الأمد. في السي شارب، يمكن استخدام مكتبة System.Threading.Tasks
لتنفيذ البرمجة المتوازية بسهولة.
مثال على استخدام Parallel.For
لتنفيذ عمليات متوازية
using System;
using System.Threading.Tasks;
public class Program
{
public static void Main(string[] args)
{
// مصفوفة من الأعداد
int[] numbers = new int[1000000];
for (int i = 0; i < numbers.Length; i++)
{
numbers[i] = i;
}
// حساب مجموع الأعداد بشكل متسلسل
long sumSequential = 0;
foreach (var number in numbers)
{
sumSequential += number;
}
Console.WriteLine($"Sum (Sequential): {sumSequential}");
// حساب مجموع الأعداد بشكل متوازي
long sumParallel = 0;
object lockObj = new object();
Parallel.For(0, numbers.Length, () => 0L, (i, loop, localSum) =>
{
localSum += numbers[i];
return localSum;
},
localSum =>
{
lock (lockObj)
{
sumParallel += localSum;
}
});
Console.WriteLine($"Sum (Parallel): {sumParallel}");
}
}
في هذا المثال، نقوم بحساب مجموع الأعداد في مصفوفة كبيرة بطريقتين: بشكل متسلسل ومتوازي. باستخدام Parallel.For
، نقسم العمل إلى مهام صغيرة يتم تنفيذها على عدة أنوية المعالج، مما يقلل من وقت التنفيذ بشكل كبير مقارنةً بالطريقة المتسلسلة.
نماذج التصميم (Design Patterns)
نماذج التصميم هي حلول جاهزة لمشاكل شائعة في تطوير البرمجيات، وتساعد في كتابة كود نظيف وقابل للصيانة. من بين النماذج الأكثر شيوعًا في السي شارب:
نموذج Singleton
يضمن نموذج Singleton وجود نسخة واحدة فقط من الكائن طوال دورة حياة التطبيق، ويوفر نقطة وصول عالمية إليه.
public class Singleton
{
private static Singleton _instance;
private static readonly object _lock = new object();
// منشئ خاص لمنع إنشاء كائنات جديدة من الخارج
private Singleton() { }
public static Singleton Instance
{
get
{
if (_instance == null)
{
lock (_lock)
{
if (_instance == null)
{
_instance = new Singleton();
}
}
}
return _instance;
}
}
public void ShowMessage()
{
Console.WriteLine("Hello from Singleton!");
}
}
public class Program
{
public static void Main(string[] args)
{
Singleton.Instance.ShowMessage(); // يطبع: Hello from Singleton!
}
}
في هذا المثال، نستخدم قفل (lock) لضمان إنشاء نسخة واحدة فقط من الكائن Singleton
حتى في بيئات متعددة الخيوط (Multithreaded).
نموذج Factory
يستخدم نموذج Factory لإنشاء كائنات دون تحديد الفئة الدقيقة للكائنات التي سيتم إنشاؤها، مما يعزز من مرونة الكود وقابليته للتوسع.
// تعريف واجهة المنتجات
public interface IProduct
{
void Display();
}
// تنفيذ واجهة IProduct بفئات مختلفة
public class ProductA : IProduct
{
public void Display()
{
Console.WriteLine("Product A Display");
}
}
public class ProductB : IProduct
{
public void Display()
{
Console.WriteLine("Product B Display");
}
}
// تعريف مصنع المنتجات
public class ProductFactory
{
public IProduct CreateProduct(string productType)
{
switch (productType)
{
case "A":
return new ProductA();
case "B":
return new ProductB();
default:
throw new ArgumentException("Invalid product type");
}
}
}
// استخدام مصنع المنتجات
public class Program
{
public static void Main(string[] args)
{
ProductFactory factory = new ProductFactory();
IProduct productA = factory.CreateProduct("A");
productA.Display(); // يطبع: Product A Display
IProduct productB = factory.CreateProduct("B");
productB.Display(); // يطبع: Product B Display
}
}
في هذا المثال، يقوم ProductFactory
بإنشاء كائنات من أنواع مختلفة بناءً على معطى productType
، مما يخفف من تعقيد إنشاء الكائنات في أماكن متعددة من التطبيق.
التفاعل مع واجهات برمجة التطبيقات (APIs) الخارجية
في كثير من التطبيقات، يكون من الضروري التفاعل مع واجهات برمجة التطبيقات الخارجية لجلب البيانات أو تنفيذ إجراءات معينة. يمكن تحقيق ذلك في السي شارب باستخدام مكتبة HttpClient
.
مثال على استدعاء API خارجي وجلب البيانات
using System;
using System.Net.Http;
using System.Threading.Tasks;
using Newtonsoft.Json;
// تعريف نموذج البيانات المتوافق مع استجابة API
public class Post
{
public int UserId { get; set; }
public int Id { get; set; }
public string Title { get; set; }
public string Body { get; set; }
}
public class Program
{
private static readonly HttpClient client = new HttpClient();
public static async Task Main(string[] args)
{
string url = "https://jsonplaceholder.typicode.com/posts/1";
try
{
HttpResponseMessage response = await client.GetAsync(url);
response.EnsureSuccessStatusCode();
string responseBody = await response.Content.ReadAsStringAsync();
Post post = JsonConvert.DeserializeObject<Post>(responseBody);
Console.WriteLine($"Title: {post.Title}");
Console.WriteLine($"Body: {post.Body}");
}
catch (HttpRequestException e)
{
Console.WriteLine($"Request error: {e.Message}");
}
}
}
في هذا المثال، نستخدم HttpClient
لإجراء طلب GET إلى API خارجي لجلب بيانات منشور معين. بعد استلام الاستجابة، نقوم بتحويل البيانات من JSON إلى كائن Post
باستخدام مكتبة Newtonsoft.Json
، ثم نقوم بطباعة العنوان والمحتوى.
الأمان في السي شارب (Security in C#)
الأمان هو جانب حيوي في تطوير البرمجيات، ولغة السي شارب توفر مجموعة من الأدوات والتقنيات لضمان أمان التطبيقات.
التحقق من صحة المدخلات (Input Validation)
من الضروري التحقق من صحة المدخلات التي يستقبلها التطبيق لمنع هجمات مثل SQL Injection وCross-Site Scripting (XSS).
public bool IsValidUsername(string username)
{
// التحقق من أن اسم المستخدم يحتوي فقط على أحرف وأرقام ولا يقل عن 5 أحرف
return !string.IsNullOrEmpty(username) && username.Length >= 5 && username.All(char.IsLetterOrDigit);
}
استخدام التشفير (Encryption)
يمكن استخدام مكتبات التشفير في السي شارب لحماية البيانات الحساسة مثل كلمات المرور والمعلومات الشخصية.
using System;
using System.Security.Cryptography;
using System.Text;
public class EncryptionHelper
{
public static string Encrypt(string plainText)
{
using (Aes aes = Aes.Create())
{
aes.GenerateKey();
aes.GenerateIV();
byte[] encrypted = EncryptStringToBytes_Aes(plainText, aes.Key, aes.IV);
return Convert.ToBase64String(aes.Key) + ":" + Convert.ToBase64String(aes.IV) + ":" + Convert.ToBase64String(encrypted);
}
}
public static string Decrypt(string cipherText)
{
string[] parts = cipherText.Split(':');
byte[] key = Convert.FromBase64String(parts[0]);
byte[] iv = Convert.FromBase64String(parts[1]);
byte[] cipherBytes = Convert.FromBase64String(parts[2]);
return DecryptStringFromBytes_Aes(cipherBytes, key, iv);
}
private static byte[] EncryptStringToBytes_Aes(string plainText, byte[] Key, byte[] IV)
{
using (Aes aesAlg = Aes.Create())
{
aesAlg.Key = Key;
aesAlg.IV = IV;
ICryptoTransform encryptor = aesAlg.CreateEncryptor(aesAlg.Key, aesAlg.IV);
using (var ms = new System.IO.MemoryStream())
{
using (var cs = new CryptoStream(ms, encryptor, CryptoStreamMode.Write))
using (var sw = new System.IO.StreamWriter(cs))
{
sw.Write(plainText);
}
return ms.ToArray();
}
}
}
private static string DecryptStringFromBytes_Aes(byte[] cipherText, byte[] Key, byte[] IV)
{
using (Aes aesAlg = Aes.Create())
{
aesAlg.Key = Key;
aesAlg.IV = IV;
ICryptoTransform decryptor = aesAlg.CreateDecryptor(aesAlg.Key, aesAlg.IV);
using (var ms = new System.IO.MemoryStream(cipherText))
using (var cs = new CryptoStream(ms, decryptor, CryptoStreamMode.Read))
using (var sr = new System.IO.StreamReader(cs))
{
return sr.ReadToEnd();
}
}
}
}
public class Program
{
public static void Main(string[] args)
{
string original = "SensitiveData123!";
string encrypted = EncryptionHelper.Encrypt(original);
string decrypted = EncryptionHelper.Decrypt(encrypted);
Console.WriteLine($"Original: {original}");
Console.WriteLine($"Encrypted: {encrypted}");
Console.WriteLine($"Decrypted: {decrypted}");
}
}
في هذا المثال، نستخدم خوارزمية AES لتشفير وفك تشفير النصوص. نقوم بإنشاء مفتاح وIV عشوائيين لكل عملية تشفير، ونخزنهم مع النص المشفر لفك التشفير لاحقًا.
إدارة الهوية والمصادقة (Identity and Authentication)
توفير نظام مصادقة قوي يضمن أن المستخدمين المصرح لهم فقط يمكنهم الوصول إلى الموارد الحساسة في التطبيق. يمكن استخدام مكتبات مثل ASP.NET Identity
لإدارة المستخدمين وتوثيقهم.
// مثال بسيط لإعداد ASP.NET Identity في تطبيق ASP.NET Core
using Microsoft.AspNetCore.Identity;
using Microsoft.EntityFrameworkCore;
public class ApplicationUser : IdentityUser
{
// يمكن إضافة خصائص إضافية هنا
}
public class AppDbContext : IdentityDbContext<ApplicationUser>
{
public AppDbContext(DbContextOptions<AppDbContext> options) : base(options) { }
}
public class Program
{
public static void Main(string[] args)
{
var builder = WebApplication.CreateBuilder(args);
// إعداد خدمات الهوية
builder.Services.AddDbContext<AppDbContext>(options =>
options.UseInMemoryDatabase("IdentityDb"));
builder.Services.AddIdentity<ApplicationUser, IdentityRole>()
.AddEntityFrameworkStores<AppDbContext>()
.AddDefaultTokenProviders();
builder.Services.AddControllers();
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
var app = builder.Build();
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI();
}
app.UseAuthentication();
app.UseAuthorization();
app.MapControllers();
app.Run();
}
}
في هذا المثال، نستخدم ASP.NET Identity
لإعداد نظام إدارة المستخدمين والمصادقة في تطبيق ASP.NET Core. يمكن توسيع هذا النظام لإضافة خصائص إضافية للمستخدمين وإدارة الأدوار والصلاحيات بشكل متقدم.
التعامل مع قواعد البيانات NoSQL
بالإضافة إلى قواعد البيانات العلائقية، تدعم السي شارب العمل مع قواعد البيانات NoSQL مثل MongoDB، والتي توفر مرونة أكبر في تخزين البيانات غير المهيكلة.
مثال على استخدام MongoDB مع السي شارب
- تثبيت مكتبة MongoDB.Driver:
استخدم الأمر التالي لتثبيت مكتبة
MongoDB.Driver
عبر NuGet:dotnet add package MongoDB.Driver
- تعريف نموذج البيانات والسياق:
using MongoDB.Bson; using MongoDB.Bson.Serialization.Attributes; public class Product { [BsonId] [BsonRepresentation(BsonType.ObjectId)] public string Id { get; set; } public string Name { get; set; } public double Price { get; set; } } public class MongoDbContext { private readonly IMongoDatabase _database; public MongoDbContext(string connectionString, string databaseName) { var client = new MongoClient(connectionString); _database = client.GetDatabase(databaseName); } public IMongoCollection<Product> Products => _database.GetCollection<Product>("Products"); }
- استخدام MongoDB في البرنامج:
using System; using System.Threading.Tasks; public class Program { public static async Task Main(string[] args) { string connectionString = "mongodb://localhost:27017"; string databaseName = "ShopDb"; MongoDbContext dbContext = new MongoDbContext(connectionString, databaseName); // إضافة منتج جديد Product newProduct = new Product { Name = "Tablet", Price = 300.00 }; await dbContext.Products.InsertOneAsync(newProduct); Console.WriteLine("Product inserted."); // استعلام عن المنتجات var products = await dbContext.Products.Find(p => p.Price > 100).ToListAsync(); Console.WriteLine("Products with price > 100:"); foreach (var product in products) { Console.WriteLine($"{product.Id}: {product.Name} - ${product.Price}"); } // تحديث منتج var filter = Builders<Product>.Filter.Eq(p => p.Name, "Tablet"); var update = Builders<Product>.Update.Set(p => p.Price, 250.00); await dbContext.Products.UpdateOneAsync(filter, update); Console.WriteLine("Product updated."); // حذف منتج await dbContext.Products.DeleteOneAsync(p => p.Name == "Tablet"); Console.WriteLine("Product deleted."); } }
في هذا المثال، نستخدم مكتبة MongoDB.Driver
للاتصال بقاعدة بيانات MongoDB، وإجراء عمليات CRUD على مجموعة المنتجات. يوفر MongoDB مرونة أكبر في تخزين البيانات غير المهيكلة، مما يجعله مناسبًا لتطبيقات تتطلب مرونة في تصميم قاعدة البيانات.
التعامل مع JSON وXML
تعد معالجة البيانات بتنسيقات مثل JSON وXML جزءًا أساسيًا من تطوير التطبيقات الحديثة، خاصة عند التفاعل مع واجهات برمجة التطبيقات (APIs) والخدمات السحابية.
معالجة JSON باستخدام Newtonsoft.Json
using System;
using Newtonsoft.Json;
public class Person
{
public string Name { get; set; }
public int Age { get; set; }
}
public class Program
{
public static void Main(string[] args)
{
// تحويل كائن إلى JSON
Person person = new Person { Name = "George", Age = 40 };
string json = JsonConvert.SerializeObject(person);
Console.WriteLine($"JSON: {json}");
// تحويل JSON إلى كائن
string jsonString = "{\"Name\":\"Hannah\",\"Age\":35}";
Person deserializedPerson = JsonConvert.DeserializeObject<Person>(jsonString);
Console.WriteLine($"Name: {deserializedPerson.Name}, Age: {deserializedPerson.Age}");
}
}
معالجة XML باستخدام System.Xml
using System;
using System.Xml.Serialization;
using System.IO;
public class Person
{
public string Name { get; set; }
public int Age { get; set; }
}
public class Program
{
public static void Main(string[] args)
{
// تحويل كائن إلى XML
Person person = new Person { Name = "Irene", Age = 29 };
XmlSerializer serializer = new XmlSerializer(typeof(Person));
using (StringWriter writer = new StringWriter())
{
serializer.Serialize(writer, person);
string xml = writer.ToString();
Console.WriteLine("XML:");
Console.WriteLine(xml);
}
// تحويل XML إلى كائن
string xmlString = "<Person><Name>Jack</Name><Age>45</Age></Person>";
using (StringReader reader = new StringReader(xmlString))
{
Person deserializedPerson = (Person)serializer.Deserialize(reader);
Console.WriteLine($"Name: {deserializedPerson.Name}, Age: {deserializedPerson.Age}");
}
}
}
في هذين المثالين، نوضح كيفية تحويل الكائنات إلى تنسيقات JSON وXML والعكس باستخدام مكتبة Newtonsoft.Json
ومعامل System.Xml.Serialization.XmlSerializer
على التوالي. هذه العمليات ضرورية عند تبادل البيانات بين الأنظمة المختلفة أو عند تخزين البيانات بتنسيقات معيارية.
تطوير تطبيقات سطح المكتب باستخدام WPF
تعتبر Windows Presentation Foundation (WPF) إطار عمل من مايكروسوفت لتطوير تطبيقات سطح المكتب ذات واجهات المستخدم الغنية والمتقدمة. توفر WPF أدوات قوية لتصميم الواجهات، إدارة البيانات، والتفاعلات الديناميكية.
مثال على إنشاء تطبيق WPF بسيط
- إنشاء مشروع WPF جديد:
استخدم الأمر التالي لإنشاء مشروع WPF جديد:
dotnet new wpf -n MyWpfApp cd MyWpfApp
- تصميم الواجهة في ملف XAML:
<!-- MainWindow.xaml --> <Window x:Class="MyWpfApp.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="My WPF App" Height="200" Width="400"> <Grid> <StackPanel VerticalAlignment="Center" HorizontalAlignment="Center"> <TextBox Name="InputTextBox" Width="200" Margin="10" /> <Button Content="Click Me" Width="100" Margin="10" Click="Button_Click"/> <TextBlock Name="OutputTextBlock" Width="200" Margin="10" TextAlignment="Center"/> </StackPanel> </Grid> </Window>
- إضافة منطق التطبيق في ملف الكود الخلفي:
// MainWindow.xaml.cs using System.Windows; namespace MyWpfApp { public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); } private void Button_Click(object sender, RoutedEventArgs e) { string input = InputTextBox.Text; OutputTextBlock.Text = $"Hello, {input}!"; } } }
- تشغيل التطبيق:
استخدم الأمر التالي لتشغيل التطبيق:
dotnet run
عند تشغيل التطبيق، ستظهر نافذة تحتوي على مربع نص، زر، ونص يظهر الرسالة الترحيبية عند النقر على الزر. هذا المثال البسيط يوضح كيفية تصميم واجهة المستخدم باستخدام XAML والتفاعل معها باستخدام كود السي شارب.
الخلاصة
تغطي لغة السي شارب مجموعة واسعة من المفاهيم والتقنيات التي تجعلها لغة برمجة قوية ومرنة تناسب مختلف أنواع التطبيقات، من تطبيقات سطح المكتب والويب إلى تطبيقات الهواتف المحمولة والألعاب. من خلال فهم واستخدام المفاهيم الأساسية والمتقدمة مثل البرمجة الكائنية، الجيليات، الانعكاس، البرمجة المتوازية، ونماذج التصميم، يمكن للمطورين بناء تطبيقات فعّالة وقابلة للصيانة تلبي احتياجات المستخدمين والسوق.
إضافة إلى ذلك، توفر السي شارب أدوات متقدمة للتعامل مع قواعد البيانات، الأمان، التفاعل مع واجهات برمجة التطبيقات، وتطوير واجهات المستخدم الغنية، مما يجعلها خيارًا مثاليًا للمشاريع البرمجية الكبيرة والمعقدة. مع استمرار تطور اللغة وإضافة ميزات جديدة، تظل السي شارب في طليعة لغات البرمجة الحديثة، مما يضمن استمرار استخدامها وانتشارها بين المطورين حول العالم.
في الختام، لغة السي شارب توفر مجموعة واسعة من الميزات التي تجعلها مناسبة لتطوير تطبيقات متنوعة ومعقدة. من خلال الأمثلة التي تناولناها، يمكن للمطورين الجدد والمتمرسين على حد سواء فهم كيفية استخدام السي شارب بفعالية لبناء تطبيقات قوية وموثوقة. مع استمرار تطور اللغة وإضافة ميزات جديدة، تظل السي شارب خيارًا قويًا ومرنًا يلبي احتياجات مختلف المشاريع البرمجية.